1
0
Fork 0
mirror of https://github.com/jellyfin/jellyfin-web synced 2025-03-30 19:56:21 +00:00

Merge branch 'master' into es6-subtitlesettings

This commit is contained in:
Dmitry Lyzo 2020-06-10 11:06:38 +03:00 committed by GitHub
commit 17f04b8042
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
146 changed files with 5890 additions and 3909 deletions

View file

@ -14,10 +14,6 @@ define([], function () {
return true;
}
if (userAgent.indexOf('nintendo') !== -1) {
return true;
}
if (userAgent.indexOf('viera') !== -1) {
return true;
}
@ -93,7 +89,7 @@ define([], function () {
var _supportsCssAnimation;
var _supportsCssAnimationWithPrefix;
function supportsCssAnimation(allowPrefix) {
// TODO: Assess if this is still needed, as all of our targets should natively support CSS animations.
if (allowPrefix) {
if (_supportsCssAnimationWithPrefix === true || _supportsCssAnimationWithPrefix === false) {
return _supportsCssAnimationWithPrefix;
@ -145,7 +141,6 @@ define([], function () {
/(chrome)[ \/]([\w.]+)/.exec(ua) ||
/(safari)[ \/]([\w.]+)/.exec(ua) ||
/(firefox)[ \/]([\w.]+)/.exec(ua) ||
/(msie) ([\w.]+)/.exec(ua) ||
ua.indexOf('compatible') < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
[];
@ -161,14 +156,6 @@ define([], function () {
if (browser === 'edge') {
platform_match = [''];
} else {
if (ua.indexOf('windows phone') !== -1 || ua.indexOf('iemobile') !== -1) {
// http://www.neowin.net/news/ie11-fakes-user-agent-to-fool-gmail-in-windows-phone-81-gdr1-update
browser = 'msie';
} else if (ua.indexOf('like gecko') !== -1 && ua.indexOf('webkit') === -1 && ua.indexOf('opera') === -1 && ua.indexOf('chrome') === -1 && ua.indexOf('safari') === -1) {
browser = 'msie';
}
}
if (browser === 'opr') {
@ -211,7 +198,7 @@ define([], function () {
browser[matched.platform] = true;
}
if (!browser.chrome && !browser.msie && !browser.edge && !browser.opera && userAgent.toLowerCase().indexOf('webkit') !== -1) {
if (!browser.chrome && !browser.edge && !browser.opera && userAgent.toLowerCase().indexOf('webkit') !== -1) {
browser.safari = true;
}
@ -224,7 +211,10 @@ define([], function () {
browser.mobile = true;
}
browser.xboxOne = userAgent.toLowerCase().indexOf('xbox') !== -1;
if (userAgent.toLowerCase().indexOf('xbox') !== -1) {
browser.xboxOne = true;
browser.tv = true;
}
browser.animate = typeof document !== 'undefined' && document.documentElement.animate != null;
browser.tizen = userAgent.toLowerCase().indexOf('tizen') !== -1 || self.tizen != null;
browser.web0s = userAgent.toLowerCase().indexOf('Web0S'.toLowerCase()) !== -1;

View file

@ -6,18 +6,10 @@ define(['browser'], function (browser) {
}
function canPlayH265(videoTestElement, options) {
if (browser.tizen || browser.orsay || browser.xboxOne || browser.web0s || options.supportsHevc) {
if (browser.tizen || browser.xboxOne || browser.web0s || options.supportsHevc) {
return true;
}
var userAgent = navigator.userAgent.toLowerCase();
if (browser.chromecast) {
var isChromecastUltra = userAgent.indexOf('aarch64') !== -1;
if (isChromecastUltra) {
return true;
}
}
if (browser.ps4) {
return false;
}
@ -31,7 +23,7 @@ define(['browser'], function (browser) {
var _supportsTextTracks;
function supportsTextTracks() {
if (browser.tizen || browser.orsay) {
if (browser.tizen) {
return true;
}
@ -53,7 +45,7 @@ define(['browser'], function (browser) {
}
function canPlayNativeHls() {
if (browser.tizen || browser.orsay) {
if (browser.tizen) {
return true;
}
@ -72,7 +64,7 @@ define(['browser'], function (browser) {
}
function supportsAc3(videoTestElement) {
if (browser.edgeUwp || browser.tizen || browser.orsay || browser.web0s) {
if (browser.edgeUwp || browser.tizen || browser.web0s) {
return true;
}
@ -80,7 +72,7 @@ define(['browser'], function (browser) {
}
function supportsEac3(videoTestElement) {
if (browser.tizen || browser.orsay || browser.web0s) {
if (browser.tizen || browser.web0s) {
return true;
}
@ -88,7 +80,7 @@ define(['browser'], function (browser) {
}
function supportsAc3InHls(videoTestElement) {
if (browser.tizen || browser.orsay || browser.web0s) {
if (browser.tizen || browser.web0s) {
return true;
}
@ -104,11 +96,11 @@ define(['browser'], function (browser) {
var typeString;
if (format === 'flac') {
if (browser.tizen || browser.orsay || browser.web0s || browser.edgeUwp) {
if (browser.tizen || browser.web0s || browser.edgeUwp) {
return true;
}
} else if (format === 'wma') {
if (browser.tizen || browser.orsay || browser.edgeUwp) {
if (browser.tizen || browser.edgeUwp) {
return true;
}
} else if (format === 'asf') {
@ -143,7 +135,7 @@ define(['browser'], function (browser) {
}
function testCanPlayMkv(videoTestElement) {
if (browser.tizen || browser.orsay || browser.web0s) {
if (browser.tizen || browser.web0s) {
return true;
}
@ -152,23 +144,6 @@ define(['browser'], function (browser) {
return true;
}
// Unfortunately there's no real way to detect mkv support
if (browser.chrome) {
// Not supported on opera tv
if (browser.operaTv) {
return false;
}
var userAgent = navigator.userAgent.toLowerCase();
// Filter out browsers based on chromium that don't support mkv
if (userAgent.indexOf('vivaldi') !== -1 || userAgent.indexOf('opera') !== -1) {
return false;
}
return true;
}
if (browser.edgeUwp) {
return true;
}
@ -177,29 +152,15 @@ define(['browser'], function (browser) {
}
function testCanPlayTs() {
return browser.tizen || browser.orsay || browser.web0s || browser.edgeUwp;
return browser.tizen || browser.web0s || browser.edgeUwp;
}
function supportsMpeg2Video() {
return browser.tizen || browser.orsay || browser.web0s || browser.edgeUwp;
return browser.tizen || browser.web0s || browser.edgeUwp;
}
function supportsVc1() {
return browser.tizen || browser.orsay || browser.web0s || browser.edgeUwp;
}
function getFlvMseDirectPlayProfile() {
var videoAudioCodecs = ['aac'];
if (!browser.edge && !browser.msie) {
videoAudioCodecs.push('mp3');
}
return {
Container: 'flv',
Type: 'Video',
VideoCodec: 'h264',
AudioCodec: videoAudioCodecs.join(',')
};
function supportsVc1(videoTestElement) {
return browser.tizen || browser.web0s || browser.edgeUwp || videoTestElement.canPlayType('video/mp4; codecs="vc-1"').replace(/no/, '');
}
function getDirectPlayProfileForVideoContainer(container, videoAudioCodecs, videoTestElement, options) {
@ -209,11 +170,11 @@ define(['browser'], function (browser) {
switch (container) {
case 'asf':
supported = browser.tizen || browser.orsay || browser.web0s || browser.edgeUwp;
supported = browser.tizen || browser.web0s || browser.edgeUwp;
videoAudioCodecs = [];
break;
case 'avi':
supported = browser.tizen || browser.orsay || browser.web0s || browser.edgeUwp;
supported = browser.tizen || browser.web0s || browser.edgeUwp;
// New Samsung TV don't support XviD/DivX
// Explicitly add supported codecs to make other codecs be transcoded
if (browser.tizenVersion >= 4) {
@ -226,29 +187,26 @@ define(['browser'], function (browser) {
break;
case 'mpg':
case 'mpeg':
supported = browser.tizen || browser.orsay || browser.web0s || browser.edgeUwp;
supported = browser.tizen || browser.web0s || browser.edgeUwp;
break;
case 'flv':
supported = browser.tizen || browser.orsay;
//if (!supported && window.MediaSource != null && window.MediaSource.isTypeSupported('video/mp4; codecs="avc1.42E01E,mp4a.40.2"')) {
// return getFlvMseDirectPlayProfile();
//}
supported = browser.tizen;
break;
case '3gp':
case 'mts':
case 'trp':
case 'vob':
case 'vro':
supported = browser.tizen || browser.orsay;
supported = browser.tizen;
break;
case 'mov':
supported = browser.tizen || browser.orsay || browser.web0s || browser.chrome || browser.edgeUwp;
supported = browser.tizen || browser.web0s || browser.chrome || browser.edgeUwp;
videoCodecs.push('h264');
break;
case 'm2ts':
supported = browser.tizen || browser.orsay || browser.web0s || browser.edgeUwp;
supported = browser.tizen || browser.web0s || browser.edgeUwp;
videoCodecs.push('h264');
if (supportsVc1()) {
if (supportsVc1(videoTestElement)) {
videoCodecs.push('vc1');
}
if (supportsMpeg2Video()) {
@ -256,7 +214,7 @@ define(['browser'], function (browser) {
}
break;
case 'wmv':
supported = browser.tizen || browser.orsay || browser.web0s || browser.edgeUwp;
supported = browser.tizen || browser.web0s || browser.edgeUwp;
videoAudioCodecs = [];
break;
case 'ts':
@ -266,7 +224,7 @@ define(['browser'], function (browser) {
videoCodecs.push('h265');
videoCodecs.push('hevc');
}
if (supportsVc1()) {
if (supportsVc1(videoTestElement)) {
videoCodecs.push('vc1');
}
if (supportsMpeg2Video()) {
@ -291,21 +249,6 @@ define(['browser'], function (browser) {
}
function getGlobalMaxVideoBitrate() {
var userAgent = navigator.userAgent.toLowerCase();
if (browser.chromecast) {
var isChromecastUltra = userAgent.indexOf('aarch64') !== -1;
if (isChromecastUltra) {
return null;
}
// This is a hack to try and detect chromecast on vizio
if (self.screen && self.screen.width >= 3800) {
return null;
}
return 30000000;
}
var isTizenFhd = false;
if (browser.tizen) {
try {
@ -350,11 +293,12 @@ define(['browser'], function (browser) {
var videoAudioCodecs = [];
var hlsVideoAudioCodecs = [];
var supportsMp3VideoAudio = videoTestElement.canPlayType('video/mp4; codecs="avc1.640029, mp4a.69"').replace(/no/, '') ||
videoTestElement.canPlayType('video/mp4; codecs="avc1.640029, mp4a.6B"').replace(/no/, '');
var supportsMp3VideoAudio = videoTestElement.canPlayType('video/mp4; codecs="avc1.640029, mp4a.69"').replace(/no/, '')
|| videoTestElement.canPlayType('video/mp4; codecs="avc1.640029, mp4a.6B"').replace(/no/, '')
|| videoTestElement.canPlayType('video/mp4; codecs="avc1.640029, mp3"').replace(/no/, '');
// Not sure how to test for this
var supportsMp2VideoAudio = browser.edgeUwp || browser.tizen || browser.orsay || browser.web0s;
var supportsMp2VideoAudio = browser.edgeUwp || browser.tizen || browser.web0s;
var maxVideoWidth = browser.xboxOne ?
(self.screen ? self.screen.width : null) :
@ -366,11 +310,6 @@ define(['browser'], function (browser) {
var canPlayAacVideoAudio = videoTestElement.canPlayType('video/mp4; codecs="avc1.640029, mp4a.40.2"').replace(/no/, '');
if (canPlayAacVideoAudio && browser.chromecast && physicalAudioChannels <= 2) {
// prioritize this first
videoAudioCodecs.push('aac');
}
// Only put mp3 first if mkv support is there
// Otherwise with HLS and mp3 audio we're seeing some browsers
// safari is lying
@ -393,11 +332,6 @@ define(['browser'], function (browser) {
}
}
if (canPlayAacVideoAudio && browser.chromecast && videoAudioCodecs.indexOf('aac') === -1) {
// prioritize this first
videoAudioCodecs.push('aac');
}
if (supportsMp3VideoAudio) {
videoAudioCodecs.push('mp3');
@ -432,7 +366,7 @@ define(['browser'], function (browser) {
videoAudioCodecs.push('mp2');
}
var supportsDts = browser.tizen || browser.orsay || browser.web0s || options.supportsDts;
var supportsDts = browser.tizen || browser.web0s || options.supportsDts || videoTestElement.canPlayType('video/mp4; codecs="dts-"').replace(/no/, '') || videoTestElement.canPlayType('video/mp4; codecs="dts+"').replace(/no/, '');
// DTS audio not supported in 2018 models (Tizen 4.0)
if (browser.tizenVersion >= 4) {
@ -444,7 +378,7 @@ define(['browser'], function (browser) {
videoAudioCodecs.push('dts');
}
if (browser.tizen || browser.orsay || browser.web0s) {
if (browser.tizen || browser.web0s) {
videoAudioCodecs.push('pcm_s16le');
videoAudioCodecs.push('pcm_s24le');
}
@ -453,7 +387,7 @@ define(['browser'], function (browser) {
videoAudioCodecs.push('truehd');
}
if (browser.tizen || browser.orsay) {
if (browser.tizen) {
videoAudioCodecs.push('aac_latm');
}
@ -497,11 +431,11 @@ define(['browser'], function (browser) {
mp4VideoCodecs.push('mpeg2video');
}
if (supportsVc1()) {
if (supportsVc1(videoTestElement)) {
mp4VideoCodecs.push('vc1');
}
if (browser.tizen || browser.orsay) {
if (browser.tizen) {
mp4VideoCodecs.push('msmpeg4v2');
}
@ -513,7 +447,7 @@ define(['browser'], function (browser) {
mp4VideoCodecs.push('vp9');
}
if (canPlayVp8 || browser.tizen || browser.orsay) {
if (canPlayVp8 || browser.tizen) {
videoAudioCodecs.push('vorbis');
}
@ -645,7 +579,7 @@ define(['browser'], function (browser) {
});
});
if (canPlayMkv && !browser.tizen && !browser.orsay && options.enableMkvProgressive !== false) {
if (canPlayMkv && !browser.tizen && options.enableMkvProgressive !== false) {
profile.TranscodingProfiles.push({
Container: 'mkv',
Type: 'Video',
@ -710,7 +644,7 @@ define(['browser'], function (browser) {
profile.CodecProfiles = [];
var supportsSecondaryAudio = browser.tizen || browser.orsay || videoTestElement.audioTracks;
var supportsSecondaryAudio = browser.tizen || videoTestElement.audioTracks;
var aacCodecProfileConditions = [];
@ -733,15 +667,6 @@ define(['browser'], function (browser) {
});
}
if (browser.chromecast) {
aacCodecProfileConditions.push({
Condition: 'LessThanEqual',
Property: 'AudioChannels',
Value: '2',
IsRequired: true
});
}
if (aacCodecProfileConditions.length) {
profile.CodecProfiles.push({
Type: 'VideoAudio',
@ -767,7 +692,7 @@ define(['browser'], function (browser) {
var maxH264Level = 42;
var h264Profiles = 'high|main|baseline|constrained baseline';
if (browser.tizen || browser.orsay || browser.web0s ||
if (browser.tizen || browser.web0s ||
videoTestElement.canPlayType('video/mp4; codecs="avc1.640833"').replace(/no/, '')) {
maxH264Level = 51;
}
@ -777,7 +702,7 @@ define(['browser'], function (browser) {
maxH264Level = 52;
}
if (browser.tizen || browser.orsay ||
if (browser.tizen ||
videoTestElement.canPlayType('video/mp4; codecs="avc1.6e0033"').replace(/no/, '')) {
// These tests are passing in safari, but playback is failing
@ -811,20 +736,13 @@ define(['browser'], function (browser) {
]
});
if (!browser.edgeUwp && !browser.tizen && !browser.orsay && !browser.web0s) {
//profile.CodecProfiles[profile.CodecProfiles.length - 1].Conditions.push({
// Condition: 'NotEquals',
// Property: 'IsAVC',
// Value: 'false',
// IsRequired: false
//});
//profile.CodecProfiles[profile.CodecProfiles.length - 1].Conditions.push({
// Condition: 'NotEquals',
// Property: 'IsInterlaced',
// Value: 'true',
// IsRequired: false
//});
if (!browser.edgeUwp && !browser.tizen && !browser.web0s) {
profile.CodecProfiles[profile.CodecProfiles.length - 1].Conditions.push({
Condition: 'NotEquals',
Property: 'IsInterlaced',
Value: 'true',
IsRequired: false
});
}
if (maxVideoWidth) {
@ -875,19 +793,6 @@ define(['browser'], function (browser) {
});
}
if (browser.chromecast) {
profile.CodecProfiles.push({
Type: 'Audio',
Codec: 'flac',
Conditions: [
{
Condition: 'LessThanEqual',
Property: 'AudioSampleRate',
Value: '96000'
}]
});
}
// Subtitle profiles
// External vtt or burn in
profile.SubtitleProfiles = [];

View file

@ -209,7 +209,7 @@ define(['datetime', 'jQuery', 'globalize', 'material-icons'], function (datetime
function onNodeOpen(event, data) {
var page = $(this).parents('.page')[0];
var node = data.node;
if (node.children && node.children) {
if (node.children) {
loadNodesToLoad(page, node);
}
if (node.li_attr && node.id != '#' && !node.li_attr.loadedFromServer) {
@ -221,7 +221,7 @@ define(['datetime', 'jQuery', 'globalize', 'material-icons'], function (datetime
function onNodeLoad(event, data) {
var page = $(this).parents('.page')[0];
var node = data.node;
if (node.children && node.children) {
if (node.children) {
loadNodesToLoad(page, node);
}
if (node.li_attr && node.id != '#' && !node.li_attr.loadedFromServer) {

View file

@ -602,27 +602,25 @@ define(['dom', 'layoutManager', 'inputManager', 'connectionManager', 'events', '
if (libraryMenuOptions) {
getUserViews(apiClient, userId).then(function (result) {
var items = result;
var html = '';
html += '<h3 class="sidebarHeader">';
html += globalize.translate('HeaderMedia');
html += '</h3>';
var html = `<h3 class="sidebarHeader">${globalize.translate('HeaderMedia')}</h3>`;
html += items.map(function (i) {
var icon = i.icon || imageHelper.getLibraryIcon(i.CollectionType);
var itemId = i.Id;
if (i.onclick) {
i.onclick;
}
const linkHtml = `<a is="emby-linkbutton" data-itemid="${itemId}" class="lnkMediaFolder navMenuOption" href="${getItemHref(i, i.CollectionType)}">
<span class="material-icons navMenuOptionIcon ${icon}"></span>
<span class="sectionName navMenuOptionText">${i.Name}</span>
</a>`;
return '<a is="emby-linkbutton" data-itemid="' + itemId + '" class="lnkMediaFolder navMenuOption" href="' + getItemHref(i, i.CollectionType) + '"><span class="material-icons navMenuOptionIcon ' + icon + '"></span><span class="sectionName navMenuOptionText">' + i.Name + '</span></a>';
return linkHtml;
}).join('');
libraryMenuOptions.innerHTML = html;
var elem = libraryMenuOptions;
var sidebarLinks = elem.querySelectorAll('.navMenuOption');
for (var i = 0, length = sidebarLinks.length; i < length; i++) {
sidebarLinks[i].removeEventListener('click', onSidebarLinkClick);
sidebarLinks[i].addEventListener('click', onSidebarLinkClick);
for (const sidebarLink of sidebarLinks) {
sidebarLink.removeEventListener('click', onSidebarLinkClick);
sidebarLink.addEventListener('click', onSidebarLinkClick);
}
});
}
@ -936,6 +934,7 @@ define(['dom', 'layoutManager', 'inputManager', 'connectionManager', 'events', '
updateMenuForPageType(isDashboardPage, isLibraryPage);
// TODO: Seems to do nothing? Check if needed (also in other views).
if (!e.detail.isRestored) {
window.scrollTo(0, 0);
}

View file

@ -69,10 +69,11 @@ define(['loading', 'listView', 'cardBuilder', 'libraryMenu', 'libraryBrowser', '
showLoadingMessage();
var query = getQuery(view);
var promise1 = ApiClient.getItems(Dashboard.getCurrentUserId(), query);
// TODO: promise2 is unused, check if necessary.
var promise2 = Dashboard.getCurrentUser();
Promise.all([promise1, promise2]).then(function (responses) {
var result = responses[0];
responses[1];
// TODO: Is the scroll necessary?
window.scrollTo(0, 0);
var html = '';
var viewStyle = getPageData(view).view;

View file

@ -1,23 +1,30 @@
/* eslint-disable indent */
import appSettings from 'appSettings';
import events from 'events';
function onSaveTimeout() {
var self = this;
self.saveTimeout = null;
self.currentApiClient.updateDisplayPreferences('usersettings', self.displayPrefs, self.currentUserId, 'emby');
function onSaveTimeout() {
var self = this;
self.saveTimeout = null;
self.currentApiClient.updateDisplayPreferences('usersettings', self.displayPrefs, self.currentUserId, 'emby');
}
function saveServerPreferences(instance) {
if (instance.saveTimeout) {
clearTimeout(instance.saveTimeout);
}
function saveServerPreferences(instance) {
if (instance.saveTimeout) {
clearTimeout(instance.saveTimeout);
}
instance.saveTimeout = setTimeout(onSaveTimeout.bind(instance), 50);
}
instance.saveTimeout = setTimeout(onSaveTimeout.bind(instance), 50);
export class UserSettings {
constructor() {
}
export function setUserInfo(userId, apiClient) {
/**
* Bind UserSettings instance to user.
* @param {string} - User identifier.
* @param {Object} - ApiClient instance.
*/
setUserInfo(userId, apiClient) {
if (this.saveTimeout) {
clearTimeout(this.saveTimeout);
}
@ -38,15 +45,24 @@ import events from 'events';
});
}
export function getData() {
// FIXME: Seems unused
getData() {
return this.displayPrefs;
}
export function importFrom(instance) {
// FIXME: Seems unused
importFrom(instance) {
this.displayPrefs = instance.getData();
}
export function set(name, value, enableOnServer) {
// FIXME: 'appSettings.set' doesn't return any value
/**
* Set value of setting.
* @param {string} name - Name of setting.
* @param {mixed} value - Value of setting.
* @param {boolean} enableOnServer - Flag to save preferences on server.
*/
set(name, value, enableOnServer) {
var userId = this.currentUserId;
var currentValue = this.get(name, enableOnServer);
var result = appSettings.set(name, value, userId);
@ -63,7 +79,13 @@ import events from 'events';
return result;
}
export function get(name, enableOnServer) {
/**
* Get value of setting.
* @param {string} name - Name of setting.
* @param {boolean} enableOnServer - Flag to return preferences from server (cached).
* @return {string} Value of setting.
*/
get(name, enableOnServer) {
var userId = this.currentUserId;
if (enableOnServer !== false && this.displayPrefs) {
return this.displayPrefs.CustomPrefs[name];
@ -72,7 +94,12 @@ import events from 'events';
return appSettings.get(name, userId);
}
export function serverConfig(config) {
/**
* Get or set user config.
* @param {Object|undefined} config - Configuration or undefined.
* @return {Object|Promise} Configuration or Promise.
*/
serverConfig(config) {
var apiClient = this.currentApiClient;
if (config) {
return apiClient.updateUserConfiguration(this.currentUserId, config);
@ -83,7 +110,12 @@ import events from 'events';
});
}
export function enableCinemaMode(val) {
/**
* Get or set 'Cinema Mode' state.
* @param {boolean|undefined} val - Flag to enable 'Cinema Mode' or undefined.
* @return {boolean} 'Cinema Mode' state.
*/
enableCinemaMode(val) {
if (val !== undefined) {
return this.set('enableCinemaMode', val.toString(), false);
}
@ -92,7 +124,12 @@ import events from 'events';
return val !== 'false';
}
export function enableNextVideoInfoOverlay(val) {
/**
* Get or set 'Next Video Info Overlay' state.
* @param {boolean|undefined} val - Flag to enable 'Next Video Info Overlay' or undefined.
* @return {boolean} 'Next Video Info Overlay' state.
*/
enableNextVideoInfoOverlay(val) {
if (val !== undefined) {
return this.set('enableNextVideoInfoOverlay', val.toString());
}
@ -101,25 +138,40 @@ import events from 'events';
return val !== 'false';
}
export function enableThemeSongs(val) {
/**
* Get or set 'Theme Songs' state.
* @param {boolean|undefined} val - Flag to enable 'Theme Songs' or undefined.
* @return {boolean} 'Theme Songs' state.
*/
enableThemeSongs(val) {
if (val !== undefined) {
return this.set('enableThemeSongs', val.toString(), false);
}
val = this.get('enableThemeSongs', false);
return val !== 'false';
return val === 'true';
}
export function enableThemeVideos(val) {
/**
* Get or set 'Theme Videos' state.
* @param {boolean|undefined} val - Flag to enable 'Theme Videos' or undefined.
* @return {boolean} 'Theme Videos' state.
*/
enableThemeVideos(val) {
if (val !== undefined) {
return this.set('enableThemeVideos', val.toString(), false);
}
val = this.get('enableThemeVideos', false);
return val !== 'false';
return val === 'true';
}
export function enableFastFadein(val) {
/**
* Get or set 'Fast Fade-in' state.
* @param {boolean|undefined} val - Flag to enable 'Fast Fade-in' or undefined.
* @return {boolean} 'Fast Fade-in' state.
*/
enableFastFadein(val) {
if (val !== undefined) {
return this.set('fastFadein', val.toString(), false);
}
@ -128,7 +180,26 @@ import events from 'events';
return val !== 'false';
}
export function enableBackdrops(val) {
/**
* Get or set 'Blurhash' state.
* @param {boolean|undefined} val - Flag to enable 'Blurhash' or undefined.
* @return {boolean} 'Blurhash' state.
*/
enableBlurhash(val) {
if (val !== undefined) {
return this.set('blurhash', val.toString(), false);
}
val = this.get('blurhash', false);
return val !== 'false';
}
/**
* Get or set 'Backdrops' state.
* @param {boolean|undefined} val - Flag to enable 'Backdrops' or undefined.
* @return {boolean} 'Backdrops' state.
*/
enableBackdrops(val) {
if (val !== undefined) {
return this.set('enableBackdrops', val.toString(), false);
}
@ -137,7 +208,26 @@ import events from 'events';
return val !== 'false';
}
export function language(val) {
/**
* Get or set 'Details Banner' state.
* @param {boolean|undefined} val - Flag to enable 'Details Banner' or undefined.
* @return {boolean} 'Details Banner' state.
*/
detailsBanner(val) {
if (val !== undefined) {
return this.set('detailsBanner', val.toString(), false);
}
val = this.get('detailsBanner', false);
return val !== 'false';
}
/**
* Get or set language.
* @param {string|undefined} val - Language.
* @return {string} Language.
*/
language(val) {
if (val !== undefined) {
return this.set('language', val.toString(), false);
}
@ -145,7 +235,12 @@ import events from 'events';
return this.get('language', false);
}
export function dateTimeLocale(val) {
/**
* Get or set datetime locale.
* @param {string|undefined} val - Datetime locale.
* @return {string} Datetime locale.
*/
dateTimeLocale(val) {
if (val !== undefined) {
return this.set('datetimelocale', val.toString(), false);
}
@ -153,7 +248,12 @@ import events from 'events';
return this.get('datetimelocale', false);
}
export function chromecastVersion(val) {
/**
* Get or set Chromecast version.
* @param {string|undefined} val - Chromecast version.
* @return {string} Chromecast version.
*/
chromecastVersion(val) {
if (val !== undefined) {
return this.set('chromecastVersion', val.toString());
}
@ -161,7 +261,12 @@ import events from 'events';
return this.get('chromecastVersion') || 'stable';
}
export function skipBackLength(val) {
/**
* Get or set amount of rewind.
* @param {number|undefined} val - Amount of rewind.
* @return {number} Amount of rewind.
*/
skipBackLength(val) {
if (val !== undefined) {
return this.set('skipBackLength', val.toString());
}
@ -169,7 +274,12 @@ import events from 'events';
return parseInt(this.get('skipBackLength') || '10000');
}
export function skipForwardLength(val) {
/**
* Get or set amount of fast forward.
* @param {number|undefined} val - Amount of fast forward.
* @return {number} Amount of fast forward.
*/
skipForwardLength(val) {
if (val !== undefined) {
return this.set('skipForwardLength', val.toString());
}
@ -177,7 +287,12 @@ import events from 'events';
return parseInt(this.get('skipForwardLength') || '30000');
}
export function dashboardTheme(val) {
/**
* Get or set theme for Dashboard.
* @param {string|undefined} val - Theme for Dashboard.
* @return {string} Theme for Dashboard.
*/
dashboardTheme(val) {
if (val !== undefined) {
return this.set('dashboardTheme', val);
}
@ -185,7 +300,12 @@ import events from 'events';
return this.get('dashboardTheme');
}
export function skin(val) {
/**
* Get or set skin.
* @param {string|undefined} val - Skin.
* @return {string} Skin.
*/
skin(val) {
if (val !== undefined) {
return this.set('skin', val, false);
}
@ -193,7 +313,12 @@ import events from 'events';
return this.get('skin', false);
}
export function theme(val) {
/**
* Get or set main theme.
* @param {string|undefined} val - Main theme.
* @return {string} Main theme.
*/
theme(val) {
if (val !== undefined) {
return this.set('appTheme', val, false);
}
@ -201,7 +326,12 @@ import events from 'events';
return this.get('appTheme', false);
}
export function screensaver(val) {
/**
* Get or set screensaver.
* @param {string|undefined} val - Screensaver.
* @return {string} Screensaver.
*/
screensaver(val) {
if (val !== undefined) {
return this.set('screensaver', val, false);
}
@ -209,7 +339,12 @@ import events from 'events';
return this.get('screensaver', false);
}
export function libraryPageSize(val) {
/**
* Get or set library page size.
* @param {number|undefined} val - Library page size.
* @return {number} Library page size.
*/
libraryPageSize(val) {
if (val !== undefined) {
return this.set('libraryPageSize', parseInt(val, 10), false);
}
@ -223,7 +358,12 @@ import events from 'events';
}
}
export function soundEffects(val) {
/**
* Get or set sound effects.
* @param {string|undefined} val - Sound effects.
* @return {string} Sound effects.
*/
soundEffects(val) {
if (val !== undefined) {
return this.set('soundeffects', val, false);
}
@ -231,7 +371,13 @@ import events from 'events';
return this.get('soundeffects', false);
}
export function loadQuerySettings(key, query) {
/**
* Load query settings.
* @param {string} key - Query key.
* @param {Object} query - Query base.
* @return {Object} Query.
*/
loadQuerySettings(key, query) {
var values = this.get(key);
if (values) {
values = JSON.parse(values);
@ -241,7 +387,12 @@ import events from 'events';
return query;
}
export function saveQuerySettings(key, query) {
/**
* Save query settings.
* @param {string} key - Query key.
* @param {Object} query - Query.
*/
saveQuerySettings(key, query) {
var values = {};
if (query.SortBy) {
values.SortBy = query.SortBy;
@ -254,52 +405,76 @@ import events from 'events';
return this.set(key, JSON.stringify(values));
}
export function getSubtitleAppearanceSettings(key) {
/**
* Get subtitle appearance settings.
* @param {string|undefined} key - Settings key.
* @return {Object} Subtitle appearance settings.
*/
getSubtitleAppearanceSettings(key) {
key = key || 'localplayersubtitleappearance3';
return JSON.parse(this.get(key, false) || '{}');
}
export function setSubtitleAppearanceSettings(value, key) {
/**
* Set subtitle appearance settings.
* @param {Object} value - Subtitle appearance settings.
* @param {string|undefined} key - Settings key.
*/
setSubtitleAppearanceSettings(value, key) {
key = key || 'localplayersubtitleappearance3';
return this.set(key, JSON.stringify(value), false);
}
export function setFilter(key, value) {
/**
* Set filter.
* @param {string} key - Filter key.
* @param {string} value - Filter value.
*/
setFilter(key, value) {
return this.set(key, value, true);
}
export function getFilter(key) {
/**
* Get filter.
* @param {string} key - Filter key.
* @return {string} Filter value.
*/
getFilter(key) {
return this.get(key, true);
}
}
/* eslint-enable indent */
export default {
setUserInfo: setUserInfo,
getData: getData,
importFrom: importFrom,
set: set,
get: get,
serverConfig: serverConfig,
enableCinemaMode: enableCinemaMode,
enableNextVideoInfoOverlay: enableNextVideoInfoOverlay,
enableThemeSongs: enableThemeSongs,
enableThemeVideos: enableThemeVideos,
enableFastFadein: enableFastFadein,
enableBackdrops: enableBackdrops,
language: language,
dateTimeLocale: dateTimeLocale,
skipBackLength: skipBackLength,
skipForwardLength: skipForwardLength,
dashboardTheme: dashboardTheme,
skin: skin,
theme: theme,
screensaver: screensaver,
libraryPageSize: libraryPageSize,
soundEffects: soundEffects,
loadQuerySettings: loadQuerySettings,
saveQuerySettings: saveQuerySettings,
getSubtitleAppearanceSettings: getSubtitleAppearanceSettings,
setSubtitleAppearanceSettings: setSubtitleAppearanceSettings,
setFilter: setFilter,
getFilter: getFilter
};
export const currentSettings = new UserSettings;
// Wrappers for non-ES6 modules and backward compatibility
export const setUserInfo = currentSettings.setUserInfo.bind(currentSettings);
export const getData = currentSettings.getData.bind(currentSettings);
export const importFrom = currentSettings.importFrom.bind(currentSettings);
export const set = currentSettings.set.bind(currentSettings);
export const get = currentSettings.get.bind(currentSettings);
export const serverConfig = currentSettings.serverConfig.bind(currentSettings);
export const enableCinemaMode = currentSettings.enableCinemaMode.bind(currentSettings);
export const enableNextVideoInfoOverlay = currentSettings.enableNextVideoInfoOverlay.bind(currentSettings);
export const enableThemeSongs = currentSettings.enableThemeSongs.bind(currentSettings);
export const enableThemeVideos = currentSettings.enableThemeVideos.bind(currentSettings);
export const enableFastFadein = currentSettings.enableFastFadein.bind(currentSettings);
export const enableBlurhash = currentSettings.enableBlurhash.bind(currentSettings);
export const enableBackdrops = currentSettings.enableBackdrops.bind(currentSettings);
export const detailsBanner = currentSettings.detailsBanner.bind(currentSettings);
export const language = currentSettings.language.bind(currentSettings);
export const dateTimeLocale = currentSettings.dateTimeLocale.bind(currentSettings);
export const chromecastVersion = currentSettings.chromecastVersion.bind(currentSettings);
export const skipBackLength = currentSettings.skipBackLength.bind(currentSettings);
export const skipForwardLength = currentSettings.skipForwardLength.bind(currentSettings);
export const dashboardTheme = currentSettings.dashboardTheme.bind(currentSettings);
export const skin = currentSettings.skin.bind(currentSettings);
export const theme = currentSettings.theme.bind(currentSettings);
export const screensaver = currentSettings.screensaver.bind(currentSettings);
export const libraryPageSize = currentSettings.libraryPageSize.bind(currentSettings);
export const soundEffects = currentSettings.soundEffects.bind(currentSettings);
export const loadQuerySettings = currentSettings.loadQuerySettings.bind(currentSettings);
export const saveQuerySettings = currentSettings.saveQuerySettings.bind(currentSettings);
export const getSubtitleAppearanceSettings = currentSettings.getSubtitleAppearanceSettings.bind(currentSettings);
export const setSubtitleAppearanceSettings = currentSettings.setSubtitleAppearanceSettings.bind(currentSettings);
export const setFilter = currentSettings.setFilter.bind(currentSettings);
export const getFilter = currentSettings.getFilter.bind(currentSettings);

View file

@ -2,7 +2,7 @@ let data;
function getConfig() {
if (data) return Promise.resolve(data);
return fetch('/config.json?nocache=' + new Date().getUTCMilliseconds()).then(response => {
return fetch('config.json?nocache=' + new Date().getUTCMilliseconds()).then(response => {
data = response.json();
return data;
}).catch(error => {
@ -12,7 +12,7 @@ function getConfig() {
}
function getDefaultConfig() {
return fetch('/config.template.json').then(function (response) {
return fetch('config.template.json').then(function (response) {
data = response.json();
return data;
});

View file

@ -228,6 +228,28 @@ var Dashboard = {
} else {
Dashboard.navigate('selectserver.html');
}
},
hideLoadingMsg: function() {
'use strict';
require(['loading'], function(loading) {
loading.hide();
});
},
showLoadingMsg: function() {
'use strict';
require(['loading'], function(loading) {
loading.show();
});
},
confirm: function(message, title, callback) {
'use strict';
require(['confirm'], function(confirm) {
confirm(message, title).then(function() {
callback(!0);
}).catch(function() {
callback(!1);
});
});
}
};
@ -375,8 +397,7 @@ var AppInfo = {};
}
}
function initRequireWithBrowser(browser) {
var bowerPath = getBowerPath();
function initRequireWithBrowser() {
var componentsPath = getComponentsPath();
var scriptsPath = getScriptsPath();
@ -385,13 +406,7 @@ var AppInfo = {};
define('lazyLoader', [componentsPath + '/lazyLoader/lazyLoaderIntersectionObserver'], returnFirstDependency);
define('shell', [scriptsPath + '/shell'], returnFirstDependency);
if ('registerElement' in document) {
define('registerElement', []);
} else if (browser.msie) {
define('registerElement', ['webcomponents'], returnFirstDependency);
} else {
define('registerElement', ['document-register-element'], returnFirstDependency);
}
define('registerElement', ['document-register-element'], returnFirstDependency);
define('alert', [componentsPath + '/alert'], returnFirstDependency);
@ -486,21 +501,22 @@ var AppInfo = {};
function loadPlugins(appHost, browser, shell) {
console.debug('loading installed plugins');
var list = [
'components/playback/playaccessvalidation',
'components/playback/experimentalwarnings',
'components/htmlAudioPlayer/plugin',
'components/htmlVideoPlayer/plugin',
'components/photoPlayer/plugin',
'components/youtubeplayer/plugin',
'components/backdropScreensaver/plugin',
'components/logoScreensaver/plugin'
'plugins/playAccessValidation/plugin',
'plugins/experimentalWarnings/plugin',
'plugins/htmlAudioPlayer/plugin',
'plugins/htmlVideoPlayer/plugin',
'plugins/photoPlayer/plugin',
'plugins/bookPlayer/plugin',
'plugins/youtubePlayer/plugin',
'plugins/backdropScreensaver/plugin',
'plugins/logoScreensaver/plugin'
];
if (appHost.supports('remotecontrol')) {
list.push('components/sessionPlayer');
list.push('plugins/sessionPlayer/plugin');
if (browser.chrome || browser.opera) {
list.push('components/chromecast/chromecastplayer');
list.push('plugins/chromecastPlayer/plugin');
}
}
@ -561,6 +577,7 @@ var AppInfo = {};
require(['components/playback/volumeosd']);
}
/* eslint-disable-next-line compat/compat */
if (navigator.mediaSession || window.NativeShell) {
require(['mediaSession']);
}
@ -616,8 +633,8 @@ var AppInfo = {};
/* eslint-enable compat/compat */
}
function onWebComponentsReady(browser) {
initRequireWithBrowser(browser);
function onWebComponentsReady() {
initRequireWithBrowser();
if (self.appMode === 'cordova' || self.appMode === 'android' || self.appMode === 'standalone') {
AppInfo.isNativeApp = true;
@ -658,8 +675,9 @@ var AppInfo = {};
playQueueManager: componentsPath + '/playback/playqueuemanager',
nowPlayingHelper: componentsPath + '/playback/nowplayinghelper',
pluginManager: componentsPath + '/pluginManager',
packageManager: componentsPath + '/packagemanager',
screensaverManager: componentsPath + '/screensavermanager'
packageManager: componentsPath + '/packageManager',
screensaverManager: componentsPath + '/screensavermanager',
chromecastHelper: 'plugins/chromecastPlayer/chromecastHelpers'
};
requirejs.onError = onRequireJsError;
@ -677,6 +695,7 @@ var AppInfo = {};
'fetch',
'flvjs',
'jstree',
'epubjs',
'jQuery',
'hlsjs',
'howler',
@ -740,7 +759,6 @@ var AppInfo = {};
// define legacy features
// TODO delete the rest of these
define('fnchecked', ['legacy/fnchecked'], returnFirstDependency);
define('legacyDashboard', ['legacy/dashboard'], returnFirstDependency);
define('legacySelectMenu', ['legacy/selectmenu'], returnFirstDependency);
// there are several objects that need to be instantiated
@ -778,7 +796,6 @@ var AppInfo = {};
define('appSettings', [scriptsPath + '/settings/appSettings'], returnFirstDependency);
define('userSettings', [scriptsPath + '/settings/userSettings'], returnFirstDependency);
define('chromecastHelper', [componentsPath + '/chromecast/chromecasthelpers'], returnFirstDependency);
define('mediaSession', [componentsPath + '/playback/mediasession'], returnFirstDependency);
define('actionsheet', [componentsPath + '/actionSheet/actionSheet'], returnFirstDependency);
define('tunerPicker', [componentsPath + '/tunerPicker'], returnFirstDependency);
@ -825,10 +842,10 @@ var AppInfo = {};
define('playbackSettings', [componentsPath + '/playbackSettings/playbackSettings'], returnFirstDependency);
define('homescreenSettings', [componentsPath + '/homeScreenSettings/homeScreenSettings'], returnFirstDependency);
define('playbackManager', [componentsPath + '/playback/playbackmanager'], getPlaybackManager);
define('timeSyncManager', [componentsPath + '/syncplay/timeSyncManager'], returnDefault);
define('groupSelectionMenu', [componentsPath + '/syncplay/groupSelectionMenu'], returnFirstDependency);
define('syncPlayManager', [componentsPath + '/syncplay/syncPlayManager'], returnDefault);
define('playbackPermissionManager', [componentsPath + '/syncplay/playbackPermissionManager'], returnDefault);
define('timeSyncManager', [componentsPath + '/syncPlay/timeSyncManager'], returnDefault);
define('groupSelectionMenu', [componentsPath + '/syncPlay/groupSelectionMenu'], returnFirstDependency);
define('syncPlayManager', [componentsPath + '/syncPlay/syncPlayManager'], returnDefault);
define('playbackPermissionManager', [componentsPath + '/syncPlay/playbackPermissionManager'], returnDefault);
define('layoutManager', [componentsPath + '/layoutManager', 'apphost'], getLayoutManager);
define('homeSections', [componentsPath + '/homesections/homesections'], returnFirstDependency);
define('playMenu', [componentsPath + '/playmenu'], returnFirstDependency);
@ -852,7 +869,7 @@ var AppInfo = {};
define('userdataButtons', [componentsPath + '/userdatabuttons/userdatabuttons'], returnFirstDependency);
define('listView', [componentsPath + '/listview/listview'], returnFirstDependency);
define('indicators', [componentsPath + '/indicators/indicators'], returnFirstDependency);
define('viewSettings', [componentsPath + '/viewsettings/viewsettings'], returnFirstDependency);
define('viewSettings', [componentsPath + '/viewSettings/viewSettings'], returnFirstDependency);
define('filterMenu', [componentsPath + '/filtermenu/filtermenu'], returnFirstDependency);
define('sortMenu', [componentsPath + '/sortmenu/sortmenu'], returnFirstDependency);
define('sanitizefilename', [componentsPath + '/sanitizeFilename'], returnFirstDependency);
@ -1138,7 +1155,7 @@ var AppInfo = {};
});
})();
return require(['browser'], onWebComponentsReady);
return onWebComponentsReady();
}();
pageClassOn('viewshow', 'standalonePage', function () {