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 quickconnect

This commit is contained in:
ConfusedPolarBear 2020-05-05 20:42:15 -05:00 committed by GitHub
commit 6d4478e8f2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
407 changed files with 15878 additions and 12346 deletions

View file

@ -0,0 +1,130 @@
define(['dom', 'focusManager'], function (dom, focusManager) {
'use strict';
var inputDisplayElement;
var currentDisplayText = '';
var currentDisplayTextContainer;
function onKeyDown(e) {
if (e.ctrlKey) {
return;
}
if (e.shiftKey) {
return;
}
if (e.altKey) {
return;
}
var key = e.key;
var chr = key ? alphanumeric(key) : null;
if (chr) {
chr = chr.toString().toUpperCase();
if (chr.length === 1) {
currentDisplayTextContainer = this.options.itemsContainer;
onAlphanumericKeyPress(e, chr);
}
}
}
function alphanumeric(value) {
var letterNumber = /^[0-9a-zA-Z]+$/;
return value.match(letterNumber);
}
function ensureInputDisplayElement() {
if (!inputDisplayElement) {
inputDisplayElement = document.createElement('div');
inputDisplayElement.classList.add('alphanumeric-shortcut');
inputDisplayElement.classList.add('hide');
document.body.appendChild(inputDisplayElement);
}
}
var alpanumericShortcutTimeout;
function clearAlphaNumericShortcutTimeout() {
if (alpanumericShortcutTimeout) {
clearTimeout(alpanumericShortcutTimeout);
alpanumericShortcutTimeout = null;
}
}
function resetAlphaNumericShortcutTimeout() {
clearAlphaNumericShortcutTimeout();
alpanumericShortcutTimeout = setTimeout(onAlphanumericShortcutTimeout, 2000);
}
function onAlphanumericKeyPress(e, chr) {
if (currentDisplayText.length >= 3) {
return;
}
ensureInputDisplayElement();
currentDisplayText += chr;
inputDisplayElement.innerHTML = currentDisplayText;
inputDisplayElement.classList.remove('hide');
resetAlphaNumericShortcutTimeout();
}
function onAlphanumericShortcutTimeout() {
var value = currentDisplayText;
var container = currentDisplayTextContainer;
currentDisplayText = '';
currentDisplayTextContainer = null;
inputDisplayElement.innerHTML = '';
inputDisplayElement.classList.add('hide');
clearAlphaNumericShortcutTimeout();
selectByShortcutValue(container, value);
}
function selectByShortcutValue(container, value) {
value = value.toUpperCase();
var focusElem;
if (value === '#') {
focusElem = container.querySelector('*[data-prefix]');
}
if (!focusElem) {
focusElem = container.querySelector('*[data-prefix^=\'' + value + '\']');
}
if (focusElem) {
focusManager.focus(focusElem);
}
}
function AlphaNumericShortcuts(options) {
this.options = options;
var keyDownHandler = onKeyDown.bind(this);
dom.addEventListener(window, 'keydown', keyDownHandler, {
passive: true
});
this.keyDownHandler = keyDownHandler;
}
AlphaNumericShortcuts.prototype.destroy = function () {
var keyDownHandler = this.keyDownHandler;
if (keyDownHandler) {
dom.removeEventListener(window, 'keydown', keyDownHandler, {
passive: true
});
this.keyDownHandler = null;
}
this.options = null;
};
return AlphaNumericShortcuts;
});

View file

@ -1,14 +1,14 @@
(function() {
"use strict";
'use strict';
function injectScriptElement(src, onload) {
if (!src) {
return;
}
var script = document.createElement("script");
var script = document.createElement('script');
if (self.dashboardVersion) {
src += "?v=" + self.dashboardVersion;
src += `?v=${self.dashboardVersion}`;
}
script.src = src;
@ -21,18 +21,28 @@
function loadSite() {
injectScriptElement(
"./libraries/alameda.js",
'./libraries/alameda.js',
function() {
// onload of require library
injectScriptElement("./scripts/site.js");
injectScriptElement('./scripts/site.js');
}
);
}
try {
Promise.resolve();
} catch (ex) {
// this checks for several cases actually, typical is
// Promise() being missing on some legacy browser, and a funky one
// is Promise() present but buggy on WebOS 2
window.Promise = undefined;
self.Promise = undefined;
}
if (!self.Promise) {
// Load Promise polyfill if they are not natively supported
injectScriptElement(
"./libraries/npo.js",
'./libraries/npo.js',
loadSite
);
} else {

View file

@ -1,26 +1,28 @@
define(["backdrop", "userSettings", "libraryMenu"], function (backdrop, userSettings, libraryMenu) {
"use strict";
define(['backdrop', 'userSettings', 'libraryMenu'], function (backdrop, userSettings, libraryMenu) {
'use strict';
var cache = {};
function enabled() {
return userSettings.enableBackdrops();
}
function getBackdropItemIds(apiClient, userId, types, parentId) {
var key = "backdrops2_" + userId + (types || "") + (parentId || "");
var key = `backdrops2_${userId + (types || '') + (parentId || '')}`;
var data = cache[key];
if (data) {
console.debug("Found backdrop id list in cache. Key: " + key);
console.debug(`Found backdrop id list in cache. Key: ${key}`);
data = JSON.parse(data);
return Promise.resolve(data);
}
var options = {
SortBy: "IsFavoriteOrLiked,Random",
SortBy: 'IsFavoriteOrLiked,Random',
Limit: 20,
Recursive: true,
IncludeItemTypes: types,
ImageTypes: "Backdrop",
ImageTypes: 'Backdrop',
ParentId: parentId,
EnableTotalRecordCount: false
};
@ -54,18 +56,17 @@ define(["backdrop", "userSettings", "libraryMenu"], function (backdrop, userSett
}
}
var cache = {};
pageClassOn("pageshow", "page", function () {
pageClassOn('pageshow', 'page', function () {
var page = this;
if (!page.classList.contains("selfBackdropPage")) {
if (page.classList.contains("backdropPage")) {
if (!page.classList.contains('selfBackdropPage')) {
if (page.classList.contains('backdropPage')) {
if (enabled()) {
var type = page.getAttribute("data-backdroptype");
var parentId = page.classList.contains("globalBackdropPage") ? "" : libraryMenu.getTopParentId();
var type = page.getAttribute('data-backdroptype');
var parentId = page.classList.contains('globalBackdropPage') ? '' : libraryMenu.getTopParentId();
showBackdrop(type, parentId);
} else {
page.classList.remove("backdropPage");
page.classList.remove('backdropPage');
backdrop.clear();
}
} else {

View file

@ -22,7 +22,7 @@ define([], function () {
return true;
}
if (userAgent.indexOf('webos') !== -1) {
if (userAgent.indexOf('web0s') !== -1) {
return true;
}
@ -77,10 +77,10 @@ define([], function () {
var camel = prop.replace(/-([a-z]|[0-9])/ig, function (all, letter) {
return (letter + '').toUpperCase();
});
// Check if the property is supported
var support = (camel in el.style);
// Create test element
var el = document.createElement('div');
// Check if the property is supported
var support = (camel in el.style);
// Assign the property and value to invoke
// the CSS interpreter
el.style.cssText = prop + ':' + value;
@ -185,7 +185,7 @@ define([], function () {
/(safari)[ \/]([\w.]+)/.exec(ua) ||
/(firefox)[ \/]([\w.]+)/.exec(ua) ||
/(msie) ([\w.]+)/.exec(ua) ||
ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
ua.indexOf('compatible') < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
[];
var versionMatch = /(version)[ \/]([\w.]+)/.exec(ua);
@ -196,17 +196,17 @@ define([], function () {
/(android)/.exec(ua) ||
[];
var browser = match[1] || "";
var browser = match[1] || '';
if (browser === "edge") {
platform_match = [""];
if (browser === 'edge') {
platform_match = [''];
} else {
if (ua.indexOf("windows phone") !== -1 || ua.indexOf("iemobile") !== -1) {
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";
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';
}
}
@ -219,7 +219,7 @@ define([], function () {
version = versionMatch[2];
}
version = version || match[2] || "0";
version = version || match[2] || '0';
var versionMajor = parseInt(version.split('.')[0]);
@ -230,7 +230,7 @@ define([], function () {
return {
browser: browser,
version: version,
platform: platform_match[0] || "",
platform: platform_match[0] || '',
versionMajor: versionMajor
};
};
@ -250,11 +250,11 @@ define([], function () {
browser[matched.platform] = true;
}
if (!browser.chrome && !browser.msie && !browser.edge && !browser.opera && userAgent.toLowerCase().indexOf("webkit") !== -1) {
if (!browser.chrome && !browser.msie && !browser.edge && !browser.opera && userAgent.toLowerCase().indexOf('webkit') !== -1) {
browser.safari = true;
}
if (userAgent.toLowerCase().indexOf("playstation 4") !== -1) {
if (userAgent.toLowerCase().indexOf('playstation 4') !== -1) {
browser.ps4 = true;
browser.tv = true;
}
@ -292,6 +292,7 @@ define([], function () {
}
if (typeof document !== 'undefined') {
/* eslint-disable-next-line compat/compat */
if (('ontouchstart' in window) || (navigator.maxTouchPoints > 0)) {
browser.touch = true;
}

View file

@ -311,9 +311,9 @@ define(['browser'], function (browser) {
try {
var isTizenUhd = webapis.productinfo.isUdPanelSupported();
isTizenFhd = !isTizenUhd;
console.debug("isTizenFhd = " + isTizenFhd);
console.debug('isTizenFhd = ' + isTizenFhd);
} catch (error) {
console.error("isUdPanelSupported() error code = " + error.code);
console.error('isUdPanelSupported() error code = ' + error.code);
}
}
@ -334,6 +334,7 @@ define(['browser'], function (browser) {
var canPlayVp8 = videoTestElement.canPlayType('video/webm; codecs="vp8"').replace(/no/, '');
var canPlayVp9 = videoTestElement.canPlayType('video/webm; codecs="vp9"').replace(/no/, '');
var canPlayAv1 = videoTestElement.canPlayType('video/webm; codecs="av1"').replace(/no/, '');
var webmAudioCodecs = ['vorbis'];
var canPlayMkv = testCanPlayMkv(videoTestElement);
@ -592,6 +593,15 @@ define(['browser'], function (browser) {
});
}
if (canPlayAv1) {
profile.DirectPlayProfiles.push({
Container: 'webm',
Type: 'Video',
AudioCodec: webmAudioCodecs.join(','),
VideoCodec: 'AV1'
});
}
profile.TranscodingProfiles = [];
var hlsBreakOnNonKeyFrames = browser.iOS || browser.osx || browser.edge || !canPlayNativeHls() ? true : false;
@ -887,6 +897,16 @@ define(['browser'], function (browser) {
Method: 'External'
});
}
if (options.enableSsaRender) {
profile.SubtitleProfiles.push({
Format: 'ass',
Method: 'External'
});
profile.SubtitleProfiles.push({
Format: 'ssa',
Method: 'External'
});
}
profile.ResponseProfiles = [];
profile.ResponseProfiles.push({

View file

@ -41,12 +41,12 @@ define(['globalize'], function (globalize) {
}
// if there's a timezone, calculate it
if (d[8] !== "Z" && d[10]) {
if (d[8] !== 'Z' && d[10]) {
var offset = d[10] * 60 * 60 * 1000;
if (d[11]) {
offset += d[11] * 60 * 1000;
}
if (d[9] === "-") {
if (d[9] === '-') {
ms -= offset;
} else {
ms += offset;
@ -159,13 +159,13 @@ define(['globalize'], function (globalize) {
var optionList = getOptionList(options);
if (optionList.length === 1 && optionList[0].name === 'weekday') {
var weekday = [];
weekday[0] = "Sun";
weekday[1] = "Mon";
weekday[2] = "Tue";
weekday[3] = "Wed";
weekday[4] = "Thu";
weekday[5] = "Fri";
weekday[6] = "Sat";
weekday[0] = 'Sun';
weekday[1] = 'Mon';
weekday[2] = 'Tue';
weekday[3] = 'Wed';
weekday[4] = 'Thu';
weekday[5] = 'Fri';
weekday[6] = 'Sat';
return weekday[date.getDay()];
}

View file

@ -1,104 +1,62 @@
import { ar, be, bg, ca, cs, da, de, el, enGB, enUS, es, faIR, fi, fr, frCA, he, hi, hr, hu, id, it, kk, ko, lt, ms, nb, nl, pl, ptBR, pt, ro, ru, sk, sl, sv, tr, uk, vi, zhCN, zhTW } from 'date-fns/locale';
import globalize from 'globalize';
export function getLocale() {
switch (globalize.getCurrentLocale()) {
case 'ar':
return ar;
case 'be-by':
return be;
case 'bg-bg':
return bg;
case 'ca':
return ca;
case 'cs':
return cs;
case 'da':
return da;
case 'de':
return de;
case 'el':
return el;
case 'en-gb':
return enGB;
case 'en-us':
return enUS;
case 'es':
return es;
case 'es-ar':
return es;
case 'es-mx':
return es;
case 'fa':
return faIR;
case 'fi':
return fi;
case 'fr':
return fr;
case 'fr-ca':
return frCA;
case 'gsw':
return de;
case 'he':
return he;
case 'hi-in':
return hi;
case 'hr':
return hr;
case 'hu':
return hu;
case 'id':
return id;
case 'it':
return it;
case 'kk':
return kk;
case 'ko':
return ko;
case 'lt-lt':
return lt;
case 'ms':
return ms;
case 'nb':
return nb;
case 'nl':
return nl;
case 'pl':
return pl;
case 'pt-br':
return ptBR;
case 'pt-pt':
return pt;
case 'ro':
return ro;
case 'ru':
return ru;
case 'sk':
return sk;
case 'sl-si':
return sl;
case 'sv':
return sv;
case 'tr':
return tr;
case 'uk':
return uk;
case 'vi':
return vi;
case 'zh-cn':
return zhCN;
case 'zh-hk':
return zhCN;
case 'zh-tw':
return zhTW;
default:
return enUS;
}
}
export const localeWithSuffix = { addSuffix: true, locale: getLocale() };
export default {
getLocale: getLocale,
localeWithSuffix: localeWithSuffix
};
import { ar, be, bg, ca, cs, da, de, el, enGB, enUS, es, faIR, fi, fr, frCA, he, hi, hr, hu, id, it, ja, kk, ko, lt, ms, nb,
nl, pl, ptBR, pt, ro, ru, sk, sl, sv, tr, uk, vi, zhCN, zhTW } from 'date-fns/locale';
import globalize from 'globalize';
const dateLocales = (locale) => ({
'ar': ar,
'be-by': be,
'bg-bg': bg,
'ca': ca,
'cs': cs,
'da': da,
'de': de,
'el': el,
'en-gb': enGB,
'en-us': enUS,
'es': es,
'es-ar': es,
'es-mx': es,
'fa': faIR,
'fi': fi,
'fr': fr,
'fr-ca': frCA,
'gsw': de,
'he': he,
'hi-in': hi,
'hr': hr,
'hu': hu,
'id': id,
'it': it,
'ja': ja,
'kk': kk,
'ko': ko,
'lt-lt': lt,
'ms': ms,
'nb': nb,
'nl': nl,
'pl': pl,
'pt-br': ptBR,
'pt-pt': pt,
'ro': ro,
'ru': ru,
'sk': sk,
'sl-si': sl,
'sv': sv,
'tr': tr,
'uk': uk,
'vi': vi,
'zh-cn': zhCN,
'zh-hk': zhCN,
'zh-tw': zhTW
})[locale];
export function getLocale() {
return dateLocales(globalize.getCurrentLocale()) || enUS;
}
export const localeWithSuffix = { addSuffix: true, locale: getLocale() };
export default {
getLocale: getLocale,
localeWithSuffix: localeWithSuffix
};

278
src/scripts/dom.js Normal file
View file

@ -0,0 +1,278 @@
/* eslint-disable indent */
/**
* Useful DOM utilities.
* @module components/dom
*/
/**
* Returns parent of element with specified attribute value.
* @param {HTMLElement} elem - Element whose parent need to find.
* @param {string} name - Attribute name.
* @param {mixed} value - Attribute value.
* @returns {HTMLElement} Parent with specified attribute value.
*/
export function parentWithAttribute(elem, name, value) {
while ((value ? elem.getAttribute(name) !== value : !elem.getAttribute(name))) {
elem = elem.parentNode;
if (!elem || !elem.getAttribute) {
return null;
}
}
return elem;
}
/**
* Returns parent of element with one of specified tag names.
* @param {HTMLElement} elem - Element whose parent need to find.
* @param {(string|Array)} tagNames - Tag name or array of tag names.
* @returns {HTMLElement} Parent with one of specified tag names.
*/
export function parentWithTag(elem, tagNames) {
// accept both string and array passed in
if (!Array.isArray(tagNames)) {
tagNames = [tagNames];
}
while (tagNames.indexOf(elem.tagName || '') === -1) {
elem = elem.parentNode;
if (!elem) {
return null;
}
}
return elem;
}
/**
* Returns _true_ if class list contains one of specified names.
* @param {DOMTokenList} classList - Class list.
* @param {Array} classNames - Array of class names.
* @returns {boolean} _true_ if class list contains one of specified names.
*/
function containsAnyClass(classList, classNames) {
for (let i = 0, length = classNames.length; i < length; i++) {
if (classList.contains(classNames[i])) {
return true;
}
}
return false;
}
/**
* Returns parent of element with one of specified class names.
* @param {HTMLElement} elem - Element whose parent need to find.
* @param {(string|Array)} classNames - Class name or array of class names.
* @returns {HTMLElement} Parent with one of specified class names.
*/
export function parentWithClass(elem, classNames) {
// accept both string and array passed in
if (!Array.isArray(classNames)) {
classNames = [classNames];
}
while (!elem.classList || !containsAnyClass(elem.classList, classNames)) {
elem = elem.parentNode;
if (!elem) {
return null;
}
}
return elem;
}
let supportsCaptureOption = false;
try {
const opts = Object.defineProperty({}, 'capture', {
// eslint-disable-next-line getter-return
get: function () {
supportsCaptureOption = true;
}
});
window.addEventListener('test', null, opts);
} catch (e) {
console.debug('error checking capture support');
}
/**
* Adds event listener to specified target.
* @param {EventTarget} target - Event target.
* @param {string} type - Event type.
* @param {function} handler - Event handler.
* @param {Object} [options] - Listener options.
*/
export function addEventListener(target, type, handler, options) {
let optionsOrCapture = options || {};
if (!supportsCaptureOption) {
optionsOrCapture = optionsOrCapture.capture;
}
target.addEventListener(type, handler, optionsOrCapture);
}
/**
* Removes event listener from specified target.
* @param {EventTarget} target - Event target.
* @param {string} type - Event type.
* @param {function} handler - Event handler.
* @param {Object} [options] - Listener options.
*/
export function removeEventListener(target, type, handler, options) {
let optionsOrCapture = options || {};
if (!supportsCaptureOption) {
optionsOrCapture = optionsOrCapture.capture;
}
target.removeEventListener(type, handler, optionsOrCapture);
}
/**
* Cached window size.
*/
let windowSize;
/**
* Flag of event listener bound.
*/
let windowSizeEventsBound;
/**
* Resets cached window size.
*/
function clearWindowSize() {
windowSize = null;
}
/**
* Returns window size.
* @returns {Object} Window size.
*/
export function getWindowSize() {
if (!windowSize) {
windowSize = {
innerHeight: window.innerHeight,
innerWidth: window.innerWidth
};
if (!windowSizeEventsBound) {
windowSizeEventsBound = true;
addEventListener(window, 'orientationchange', clearWindowSize, { passive: true });
addEventListener(window, 'resize', clearWindowSize, { passive: true });
}
}
return windowSize;
}
/**
* Standard screen widths.
*/
const standardWidths = [480, 720, 1280, 1440, 1920, 2560, 3840, 5120, 7680];
/**
* Returns screen width.
* @returns {number} Screen width.
*/
export function getScreenWidth() {
let width = window.innerWidth;
const height = window.innerHeight;
if (height > width) {
width = height * (16.0 / 9.0);
}
const closest = standardWidths.sort(function (a, b) {
return Math.abs(width - a) - Math.abs(width - b);
})[0];
return closest;
}
/**
* Name of animation end event.
*/
let _animationEvent;
/**
* Returns name of animation end event.
* @returns {string} Name of animation end event.
*/
export function whichAnimationEvent() {
if (_animationEvent) {
return _animationEvent;
}
const el = document.createElement('div');
const animations = {
'animation': 'animationend',
'OAnimation': 'oAnimationEnd',
'MozAnimation': 'animationend',
'WebkitAnimation': 'webkitAnimationEnd'
};
for (let t in animations) {
if (el.style[t] !== undefined) {
_animationEvent = animations[t];
return animations[t];
}
}
_animationEvent = 'animationend';
return _animationEvent;
}
/**
* Returns name of animation cancel event.
* @returns {string} Name of animation cancel event.
*/
export function whichAnimationCancelEvent() {
return whichAnimationEvent().replace('animationend', 'animationcancel').replace('AnimationEnd', 'AnimationCancel');
}
/**
* Name of transition end event.
*/
let _transitionEvent;
/**
* Returns name of transition end event.
* @returns {string} Name of transition end event.
*/
export function whichTransitionEvent() {
if (_transitionEvent) {
return _transitionEvent;
}
const el = document.createElement('div');
const transitions = {
'transition': 'transitionend',
'OTransition': 'oTransitionEnd',
'MozTransition': 'transitionend',
'WebkitTransition': 'webkitTransitionEnd'
};
for (let t in transitions) {
if (el.style[t] !== undefined) {
_transitionEvent = transitions[t];
return transitions[t];
}
}
_transitionEvent = 'transitionend';
return _transitionEvent;
}
/* eslint-enable indent */
export default {
parentWithAttribute: parentWithAttribute,
parentWithClass: parentWithClass,
parentWithTag: parentWithTag,
addEventListener: addEventListener,
removeEventListener: removeEventListener,
getWindowSize: getWindowSize,
getScreenWidth: getScreenWidth,
whichTransitionEvent: whichTransitionEvent,
whichAnimationEvent: whichAnimationEvent,
whichAnimationCancelEvent: whichAnimationCancelEvent
};

View file

@ -1,5 +1,5 @@
define(["datetime", "jQuery", "material-icons"], function (datetime, $) {
"use strict";
define(['datetime', 'jQuery', 'globalize', 'material-icons'], function (datetime, $, globalize) {
'use strict';
function getNode(item, folderState, selected) {
var htmlName = getNodeInnerHtml(item);
@ -7,7 +7,7 @@ define(["datetime", "jQuery", "material-icons"], function (datetime, $) {
id: item.Id,
text: htmlName,
state: {
opened: item.IsFolder && folderState == "open",
opened: item.IsFolder && folderState == 'open',
selected: selected
},
li_attr: {
@ -17,7 +17,7 @@ define(["datetime", "jQuery", "material-icons"], function (datetime, $) {
};
if (item.IsFolder) {
node.children = [{
text: "Loading...",
text: 'Loading...',
icon: false
}];
node.icon = false;
@ -36,30 +36,30 @@ define(["datetime", "jQuery", "material-icons"], function (datetime, $) {
function getNodeInnerHtml(item) {
var name = item.Name;
if (item.Number) {
name = item.Number + " - " + name;
name = item.Number + ' - ' + name;
}
if (item.IndexNumber != null && item.Type != "Season") {
name = item.IndexNumber + " - " + name;
if (item.IndexNumber != null && item.Type != 'Season') {
name = item.IndexNumber + ' - ' + name;
}
var htmlName = "<div class='editorNode'>";
if (item.IsFolder) {
htmlName += '<i class="material-icons metadataSidebarIcon">folder</i>';
} else if (item.MediaType === "Video") {
htmlName += '<i class="material-icons metadataSidebarIcon">movie</i>';
} else if (item.MediaType === "Audio") {
htmlName += '<i class="material-icons metadataSidebarIcon">audiotrack</i>';
} else if (item.Type === "TvChannel") {
htmlName += '<i class="material-icons metadataSidebarIcon live_tv"></i>';
} else if (item.MediaType === "Photo") {
htmlName += '<i class="material-icons metadataSidebarIcon">photo</i>';
} else if (item.MediaType === "Book") {
htmlName += '<i class="material-icons metadataSidebarIcon">book</i>';
htmlName += '<span class="material-icons metadataSidebarIcon folder"></span>';
} else if (item.MediaType === 'Video') {
htmlName += '<span class="material-icons metadataSidebarIcon movie"></span>';
} else if (item.MediaType === 'Audio') {
htmlName += '<span class="material-icons metadataSidebarIcon audiotrack"></span>';
} else if (item.Type === 'TvChannel') {
htmlName += '<span class="material-icons metadataSidebarIcon live_tv"></span>';
} else if (item.MediaType === 'Photo') {
htmlName += '<span class="material-icons metadataSidebarIcon photo"></span>';
} else if (item.MediaType === 'Book') {
htmlName += '<span class="material-icons metadataSidebarIcon book"></span>';
}
if (item.LockData) {
htmlName += '<i class="material-icons metadataSidebarIcon">lock</i>';
htmlName += '<span class="material-icons metadataSidebarIcon lock"></span>';
}
htmlName += name;
htmlName += "</div>";
htmlName += '</div>';
return htmlName;
}
@ -69,36 +69,36 @@ define(["datetime", "jQuery", "material-icons"], function (datetime, $) {
}).then(function (result) {
var nodes = [];
nodes.push({
id: "MediaFolders",
text: Globalize.translate("HeaderMediaFolders"),
id: 'MediaFolders',
text: globalize.translate('HeaderMediaFolders'),
state: {
opened: true
},
li_attr: {
itemtype: "mediafolders",
itemtype: 'mediafolders',
loadedFromServer: true
},
icon: false
});
if (result.TotalRecordCount) {
nodes.push({
id: "livetv",
text: Globalize.translate("HeaderLiveTV"),
id: 'livetv',
text: globalize.translate('HeaderLiveTV'),
state: {
opened: false
},
li_attr: {
itemtype: "livetv"
itemtype: 'livetv'
},
children: [{
text: "Loading...",
text: 'Loading...',
icon: false
}],
icon: false
});
}
callback.call(scope, nodes);
nodesToLoad.push("MediaFolders");
nodesToLoad.push('MediaFolders');
});
}
@ -108,7 +108,7 @@ define(["datetime", "jQuery", "material-icons"], function (datetime, $) {
AddCurrentProgram: false
}).then(function (result) {
var nodes = result.Items.map(function (i) {
var state = openItems.indexOf(i.Id) == -1 ? "closed" : "open";
var state = openItems.indexOf(i.Id) == -1 ? 'closed' : 'open';
return getNode(i, state, false);
});
callback(nodes);
@ -116,9 +116,9 @@ define(["datetime", "jQuery", "material-icons"], function (datetime, $) {
}
function loadMediaFolders(page, scope, openItems, callback) {
ApiClient.getJSON(ApiClient.getUrl("Library/MediaFolders")).then(function (result) {
ApiClient.getJSON(ApiClient.getUrl('Library/MediaFolders')).then(function (result) {
var nodes = result.Items.map(function (n) {
var state = openItems.indexOf(n.Id) == -1 ? "closed" : "open";
var state = openItems.indexOf(n.Id) == -1 ? 'closed' : 'open';
return getNode(n, state, false);
});
callback.call(scope, nodes);
@ -132,21 +132,21 @@ define(["datetime", "jQuery", "material-icons"], function (datetime, $) {
function loadNode(page, scope, node, openItems, selectedId, currentUser, callback) {
var id = node.id;
if (id == "#") {
if (id == '#') {
loadChildrenOfRootNode(page, scope, callback);
return;
}
if (id == "livetv") {
if (id == 'livetv') {
loadLiveTvChannels(id, openItems, callback);
return;
}
if (id == "MediaFolders") {
if (id == 'MediaFolders') {
loadMediaFolders(page, scope, openItems, callback);
return;
}
var query = {
ParentId: id,
Fields: "Settings",
Fields: 'Settings',
IsVirtualUnaired: false,
IsMissing: false,
EnableTotalRecordCount: false,
@ -154,12 +154,12 @@ define(["datetime", "jQuery", "material-icons"], function (datetime, $) {
EnableUserData: false
};
var itemtype = node.li_attr.itemtype;
if (itemtype != "Season" && itemtype != "Series") {
query.SortBy = "SortName";
if (itemtype != 'Season' && itemtype != 'Series') {
query.SortBy = 'SortName';
}
ApiClient.getItems(Dashboard.getCurrentUserId(), query).then(function (result) {
var nodes = result.Items.map(function (n) {
var state = openItems.indexOf(n.Id) == -1 ? "closed" : "open";
var state = openItems.indexOf(n.Id) == -1 ? 'closed' : 'open';
return getNode(n, state, n.Id == selectedId);
});
callback.call(scope, nodes);
@ -172,14 +172,14 @@ define(["datetime", "jQuery", "material-icons"], function (datetime, $) {
}
function scrollToNode(id) {
var elem = $("#" + id)[0];
var elem = $('#' + id)[0];
if (elem) {
elem.scrollIntoView();
}
}
function initializeTree(page, currentUser, openItems, selectedId) {
require(["jstree"], function () {
require(['jstree'], function () {
initializeTreeInternal(page, currentUser, openItems, selectedId);
});
}
@ -192,41 +192,41 @@ define(["datetime", "jQuery", "material-icons"], function (datetime, $) {
serverItemType: node.li_attr.serveritemtype,
collectionType: node.li_attr.collectiontype
};
if (eventData.itemType != "livetv" && eventData.itemType != "mediafolders") {
if (eventData.itemType != 'livetv' && eventData.itemType != 'mediafolders') {
{
this.dispatchEvent(new CustomEvent("itemclicked", {
this.dispatchEvent(new CustomEvent('itemclicked', {
detail: eventData,
bubbles: true,
cancelable: false
}));
}
document.querySelector(".editPageSidebar").classList.add("editPageSidebar-withcontent");
document.querySelector('.editPageSidebar').classList.add('editPageSidebar-withcontent');
} else {
document.querySelector(".editPageSidebar").classList.remove("editPageSidebar-withcontent");
document.querySelector('.editPageSidebar').classList.remove('editPageSidebar-withcontent');
}
}
function onNodeOpen(event, data) {
var page = $(this).parents(".page")[0];
var page = $(this).parents('.page')[0];
var node = data.node;
if (node.children && node.children) {
loadNodesToLoad(page, node);
}
if (node.li_attr && node.id != "#" && !node.li_attr.loadedFromServer) {
if (node.li_attr && node.id != '#' && !node.li_attr.loadedFromServer) {
node.li_attr.loadedFromServer = true;
$.jstree.reference(".libraryTree", page).load_node(node.id, loadNodeCallback);
$.jstree.reference('.libraryTree', page).load_node(node.id, loadNodeCallback);
}
}
function onNodeLoad(event, data) {
var page = $(this).parents(".page")[0];
var page = $(this).parents('.page')[0];
var node = data.node;
if (node.children && node.children) {
loadNodesToLoad(page, node);
}
if (node.li_attr && node.id != "#" && !node.li_attr.loadedFromServer) {
if (node.li_attr && node.id != '#' && !node.li_attr.loadedFromServer) {
node.li_attr.loadedFromServer = true;
$.jstree.reference(".libraryTree", page).load_node(node.id, loadNodeCallback);
$.jstree.reference('.libraryTree', page).load_node(node.id, loadNodeCallback);
}
}
@ -234,18 +234,18 @@ define(["datetime", "jQuery", "material-icons"], function (datetime, $) {
nodesToLoad = [];
selectedNodeId = null;
$.jstree.destroy();
$(".libraryTree", page).jstree({
"plugins": ["wholerow"],
$('.libraryTree', page).jstree({
'plugins': ['wholerow'],
core: {
check_callback: true,
data: function (node, callback) {
loadNode(page, this, node, openItems, selectedId, currentUser, callback);
},
themes: {
variant: "large"
variant: 'large'
}
}
}).off("select_node.jstree", onNodeSelect).on("select_node.jstree", onNodeSelect).off("open_node.jstree", onNodeOpen).on("open_node.jstree", onNodeOpen).off("load_node.jstree", onNodeLoad).on("load_node.jstree", onNodeLoad);
}).off('select_node.jstree', onNodeSelect).on('select_node.jstree', onNodeSelect).off('open_node.jstree', onNodeOpen).on('open_node.jstree', onNodeOpen).off('load_node.jstree', onNodeLoad).on('load_node.jstree', onNodeLoad);
}
function loadNodesToLoad(page, node) {
@ -256,7 +256,7 @@ define(["datetime", "jQuery", "material-icons"], function (datetime, $) {
nodesToLoad = nodesToLoad.filter(function (n) {
return n != child;
});
$.jstree.reference(".libraryTree", page).load_node(child, loadNodeCallback);
$.jstree.reference('.libraryTree', page).load_node(child, loadNodeCallback);
}
}
}
@ -270,14 +270,14 @@ define(["datetime", "jQuery", "material-icons"], function (datetime, $) {
}
function updateEditorNode(page, item) {
var elem = $("#" + item.Id + ">a", page)[0];
var elem = $('#' + item.Id + '>a', page)[0];
if (elem == null) {
return;
}
$(".editorNode", elem).remove();
$('.editorNode', elem).remove();
$(elem).append(getNodeInnerHtml(item));
if (item.IsFolder) {
var tree = jQuery.jstree._reference(".libraryTree");
var tree = jQuery.jstree._reference('.libraryTree');
var currentNode = tree._get_node(null, false);
tree.refresh(currentNode);
}
@ -292,15 +292,15 @@ define(["datetime", "jQuery", "material-icons"], function (datetime, $) {
return itemId;
}
var url = window.location.hash || window.location.href;
return getParameterByName("id", url);
return getParameterByName('id', url);
}
var nodesToLoad = [];
var selectedNodeId;
$(document).on("itemsaved", ".metadataEditorPage", function (e, item) {
$(document).on('itemsaved', '.metadataEditorPage', function (e, item) {
updateEditorNode(this, item);
}).on("pagebeforeshow", ".metadataEditorPage", function () {
require(["css!assets/css/metadataeditor.css"]);
}).on("pagebeforeshow", ".metadataEditorPage", function () {
}).on('pagebeforeshow', '.metadataEditorPage', function () {
require(['css!assets/css/metadataeditor.css']);
}).on('pagebeforeshow', '.metadataEditorPage', function () {
var page = this;
Dashboard.getCurrentUser().then(function (user) {
var id = getCurrentItemId();
@ -315,9 +315,9 @@ define(["datetime", "jQuery", "material-icons"], function (datetime, $) {
initializeTree(page, user, []);
}
});
}).on("pagebeforehide", ".metadataEditorPage", function () {
}).on('pagebeforehide', '.metadataEditorPage', function () {
var page = this;
$(".libraryTree", page).off("select_node.jstree", onNodeSelect).off("open_node.jstree", onNodeOpen).off("load_node.jstree", onNodeLoad);
$('.libraryTree', page).off('select_node.jstree', onNodeSelect).off('open_node.jstree', onNodeOpen).off('load_node.jstree', onNodeLoad);
});
var itemId;
window.MetadataEditor = {

13
src/scripts/filesystem.js Normal file
View file

@ -0,0 +1,13 @@
export function fileExists(path) {
if (window.NativeShell && window.NativeShell.FileSystem) {
return window.NativeShell.FileSystem.fileExists(path);
}
return Promise.reject();
}
export function directoryExists(path) {
if (window.NativeShell && window.NativeShell.FileSystem) {
return window.NativeShell.FileSystem.directoryExists(path);
}
return Promise.reject();
}

410
src/scripts/gamepadtokey.js Normal file
View file

@ -0,0 +1,410 @@
// # The MIT License (MIT)
// #
// # Copyright (c) 2016 Microsoft. All rights reserved.
// #
// # Permission is hereby granted, free of charge, to any person obtaining a copy
// # of this software and associated documentation files (the "Software"), to deal
// # in the Software without restriction, including without limitation the rights
// # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// # copies of the Software, and to permit persons to whom the Software is
// # furnished to do so, subject to the following conditions:
// #
// # The above copyright notice and this permission notice shall be included in
// # all copies or substantial portions of the Software.
// #
// # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// # THE SOFTWARE.
require(['apphost'], function (appHost) {
'use strict';
var _GAMEPAD_A_BUTTON_INDEX = 0;
var _GAMEPAD_B_BUTTON_INDEX = 1;
var _GAMEPAD_DPAD_UP_BUTTON_INDEX = 12;
var _GAMEPAD_DPAD_DOWN_BUTTON_INDEX = 13;
var _GAMEPAD_DPAD_LEFT_BUTTON_INDEX = 14;
var _GAMEPAD_DPAD_RIGHT_BUTTON_INDEX = 15;
var _GAMEPAD_A_KEY = 'GamepadA';
var _GAMEPAD_B_KEY = 'GamepadB';
var _GAMEPAD_DPAD_UP_KEY = 'GamepadDPadUp';
var _GAMEPAD_DPAD_DOWN_KEY = 'GamepadDPadDown';
var _GAMEPAD_DPAD_LEFT_KEY = 'GamepadDPadLeft';
var _GAMEPAD_DPAD_RIGHT_KEY = 'GamepadDPadRight';
var _GAMEPAD_LEFT_THUMBSTICK_UP_KEY = 'GamepadLeftThumbStickUp';
var _GAMEPAD_LEFT_THUMBSTICK_DOWN_KEY = 'GamepadLeftThumbStickDown';
var _GAMEPAD_LEFT_THUMBSTICK_LEFT_KEY = 'GamepadLeftThumbStickLeft';
var _GAMEPAD_LEFT_THUMBSTICK_RIGHT_KEY = 'GamepadLeftThumbStickRight';
var _GAMEPAD_A_KEYCODE = 0;
var _GAMEPAD_B_KEYCODE = 27;
var _GAMEPAD_DPAD_UP_KEYCODE = 38;
var _GAMEPAD_DPAD_DOWN_KEYCODE = 40;
var _GAMEPAD_DPAD_LEFT_KEYCODE = 37;
var _GAMEPAD_DPAD_RIGHT_KEYCODE = 39;
var _GAMEPAD_LEFT_THUMBSTICK_UP_KEYCODE = 38;
var _GAMEPAD_LEFT_THUMBSTICK_DOWN_KEYCODE = 40;
var _GAMEPAD_LEFT_THUMBSTICK_LEFT_KEYCODE = 37;
var _GAMEPAD_LEFT_THUMBSTICK_RIGHT_KEYCODE = 39;
var _THUMB_STICK_THRESHOLD = 0.75;
var _leftThumbstickUpPressed = false;
var _leftThumbstickDownPressed = false;
var _leftThumbstickLeftPressed = false;
var _leftThumbstickRightPressed = false;
var _dPadUpPressed = false;
var _dPadDownPressed = false;
var _dPadLeftPressed = false;
var _dPadRightPressed = false;
var _gamepadAPressed = false;
var _gamepadBPressed = false;
// The set of buttons on the gamepad we listen for.
var ProcessedButtons = [
_GAMEPAD_DPAD_UP_BUTTON_INDEX,
_GAMEPAD_DPAD_DOWN_BUTTON_INDEX,
_GAMEPAD_DPAD_LEFT_BUTTON_INDEX,
_GAMEPAD_DPAD_RIGHT_BUTTON_INDEX,
_GAMEPAD_A_BUTTON_INDEX,
_GAMEPAD_B_BUTTON_INDEX
];
var _ButtonPressedState = {};
_ButtonPressedState.getgamepadA = function () {
return _gamepadAPressed;
};
_ButtonPressedState.setgamepadA = function (newPressedState) {
raiseKeyEvent(_gamepadAPressed, newPressedState, _GAMEPAD_A_KEY, _GAMEPAD_A_KEYCODE, false, true);
_gamepadAPressed = newPressedState;
};
_ButtonPressedState.getgamepadB = function () {
return _gamepadBPressed;
};
_ButtonPressedState.setgamepadB = function (newPressedState) {
raiseKeyEvent(_gamepadBPressed, newPressedState, _GAMEPAD_B_KEY, _GAMEPAD_B_KEYCODE);
_gamepadBPressed = newPressedState;
};
_ButtonPressedState.getleftThumbstickUp = function () {
return _leftThumbstickUpPressed;
};
_ButtonPressedState.setleftThumbstickUp = function (newPressedState) {
raiseKeyEvent(_leftThumbstickUpPressed, newPressedState, _GAMEPAD_LEFT_THUMBSTICK_UP_KEY, _GAMEPAD_LEFT_THUMBSTICK_UP_KEYCODE, true);
_leftThumbstickUpPressed = newPressedState;
};
_ButtonPressedState.getleftThumbstickDown = function () {
return _leftThumbstickDownPressed;
};
_ButtonPressedState.setleftThumbstickDown = function (newPressedState) {
raiseKeyEvent(_leftThumbstickDownPressed, newPressedState, _GAMEPAD_LEFT_THUMBSTICK_DOWN_KEY, _GAMEPAD_LEFT_THUMBSTICK_DOWN_KEYCODE, true);
_leftThumbstickDownPressed = newPressedState;
};
_ButtonPressedState.getleftThumbstickLeft = function () {
return _leftThumbstickLeftPressed;
};
_ButtonPressedState.setleftThumbstickLeft = function (newPressedState) {
raiseKeyEvent(_leftThumbstickLeftPressed, newPressedState, _GAMEPAD_LEFT_THUMBSTICK_LEFT_KEY, _GAMEPAD_LEFT_THUMBSTICK_LEFT_KEYCODE, true);
_leftThumbstickLeftPressed = newPressedState;
};
_ButtonPressedState.getleftThumbstickRight = function () {
return _leftThumbstickRightPressed;
};
_ButtonPressedState.setleftThumbstickRight = function (newPressedState) {
raiseKeyEvent(_leftThumbstickRightPressed, newPressedState, _GAMEPAD_LEFT_THUMBSTICK_RIGHT_KEY, _GAMEPAD_LEFT_THUMBSTICK_RIGHT_KEYCODE, true);
_leftThumbstickRightPressed = newPressedState;
};
_ButtonPressedState.getdPadUp = function () {
return _dPadUpPressed;
};
_ButtonPressedState.setdPadUp = function (newPressedState) {
raiseKeyEvent(_dPadUpPressed, newPressedState, _GAMEPAD_DPAD_UP_KEY, _GAMEPAD_DPAD_UP_KEYCODE, true);
_dPadUpPressed = newPressedState;
};
_ButtonPressedState.getdPadDown = function () {
return _dPadDownPressed;
};
_ButtonPressedState.setdPadDown = function (newPressedState) {
raiseKeyEvent(_dPadDownPressed, newPressedState, _GAMEPAD_DPAD_DOWN_KEY, _GAMEPAD_DPAD_DOWN_KEYCODE, true);
_dPadDownPressed = newPressedState;
};
_ButtonPressedState.getdPadLeft = function () {
return _dPadLeftPressed;
};
_ButtonPressedState.setdPadLeft = function (newPressedState) {
raiseKeyEvent(_dPadLeftPressed, newPressedState, _GAMEPAD_DPAD_LEFT_KEY, _GAMEPAD_DPAD_LEFT_KEYCODE, true);
_dPadLeftPressed = newPressedState;
};
_ButtonPressedState.getdPadRight = function () {
return _dPadRightPressed;
};
_ButtonPressedState.setdPadRight = function (newPressedState) {
raiseKeyEvent(_dPadRightPressed, newPressedState, _GAMEPAD_DPAD_RIGHT_KEY, _GAMEPAD_DPAD_RIGHT_KEYCODE, true);
_dPadRightPressed = newPressedState;
};
var times = {};
function throttle(key) {
var time = times[key] || 0;
var now = new Date().getTime();
if ((now - time) >= 200) {
//times[key] = now;
return true;
}
return false;
}
function resetThrottle(key) {
times[key] = new Date().getTime();
}
var isElectron = navigator.userAgent.toLowerCase().indexOf('electron') !== -1;
function allowInput() {
// This would be nice but always seems to return true with electron
if (!isElectron && document.hidden) { /* eslint-disable-line compat/compat */
return false;
}
if (appHost.getWindowState() === 'Minimized') {
return false;
}
return true;
}
function raiseEvent(name, key, keyCode) {
if (!allowInput()) {
return;
}
var event = document.createEvent('Event');
event.initEvent(name, true, true);
event.key = key;
event.keyCode = keyCode;
(document.activeElement || document.body).dispatchEvent(event);
}
function clickElement(elem) {
if (!allowInput()) {
return;
}
elem.click();
}
function raiseKeyEvent(oldPressedState, newPressedState, key, keyCode, enableRepeatKeyDown, clickonKeyUp) {
// No-op if oldPressedState === newPressedState
if (newPressedState === true) {
// button down
var fire = false;
// always fire if this is the initial down press
if (oldPressedState === false) {
fire = true;
resetThrottle(key);
} else if (enableRepeatKeyDown) {
fire = throttle(key);
}
if (fire && keyCode) {
raiseEvent('keydown', key, keyCode);
}
} else if (newPressedState === false && oldPressedState === true) {
resetThrottle(key);
// button up
if (keyCode) {
raiseEvent('keyup', key, keyCode);
}
if (clickonKeyUp) {
clickElement(document.activeElement || window);
}
}
}
var inputLoopTimer;
function runInputLoop() {
// Get the latest gamepad state.
var gamepads = navigator.getGamepads(); /* eslint-disable-line compat/compat */
for (var i = 0, len = gamepads.length; i < len; i++) {
var gamepad = gamepads[i];
if (!gamepad) {
continue;
}
// Iterate through the axes
var axes = gamepad.axes;
var leftStickX = axes[0];
var leftStickY = axes[1];
if (leftStickX > _THUMB_STICK_THRESHOLD) { // Right
_ButtonPressedState.setleftThumbstickRight(true);
} else if (leftStickX < -_THUMB_STICK_THRESHOLD) { // Left
_ButtonPressedState.setleftThumbstickLeft(true);
} else if (leftStickY < -_THUMB_STICK_THRESHOLD) { // Up
_ButtonPressedState.setleftThumbstickUp(true);
} else if (leftStickY > _THUMB_STICK_THRESHOLD) { // Down
_ButtonPressedState.setleftThumbstickDown(true);
} else {
_ButtonPressedState.setleftThumbstickLeft(false);
_ButtonPressedState.setleftThumbstickRight(false);
_ButtonPressedState.setleftThumbstickUp(false);
_ButtonPressedState.setleftThumbstickDown(false);
}
// Iterate through the buttons to see if Left thumbstick, DPad, A and B are pressed.
var buttons = gamepad.buttons;
for (var j = 0, len = buttons.length; j < len; j++) {
if (ProcessedButtons.indexOf(j) !== -1) {
if (buttons[j].pressed) {
switch (j) {
case _GAMEPAD_DPAD_UP_BUTTON_INDEX:
_ButtonPressedState.setdPadUp(true);
break;
case _GAMEPAD_DPAD_DOWN_BUTTON_INDEX:
_ButtonPressedState.setdPadDown(true);
break;
case _GAMEPAD_DPAD_LEFT_BUTTON_INDEX:
_ButtonPressedState.setdPadLeft(true);
break;
case _GAMEPAD_DPAD_RIGHT_BUTTON_INDEX:
_ButtonPressedState.setdPadRight(true);
break;
case _GAMEPAD_A_BUTTON_INDEX:
_ButtonPressedState.setgamepadA(true);
break;
case _GAMEPAD_B_BUTTON_INDEX:
_ButtonPressedState.setgamepadB(true);
break;
default:
// No-op
break;
}
} else {
switch (j) {
case _GAMEPAD_DPAD_UP_BUTTON_INDEX:
if (_ButtonPressedState.getdPadUp()) {
_ButtonPressedState.setdPadUp(false);
}
break;
case _GAMEPAD_DPAD_DOWN_BUTTON_INDEX:
if (_ButtonPressedState.getdPadDown()) {
_ButtonPressedState.setdPadDown(false);
}
break;
case _GAMEPAD_DPAD_LEFT_BUTTON_INDEX:
if (_ButtonPressedState.getdPadLeft()) {
_ButtonPressedState.setdPadLeft(false);
}
break;
case _GAMEPAD_DPAD_RIGHT_BUTTON_INDEX:
if (_ButtonPressedState.getdPadRight()) {
_ButtonPressedState.setdPadRight(false);
}
break;
case _GAMEPAD_A_BUTTON_INDEX:
if (_ButtonPressedState.getgamepadA()) {
_ButtonPressedState.setgamepadA(false);
}
break;
case _GAMEPAD_B_BUTTON_INDEX:
if (_ButtonPressedState.getgamepadB()) {
_ButtonPressedState.setgamepadB(false);
}
break;
default:
// No-op
break;
}
}
}
}
}
// Schedule the next one
inputLoopTimer = requestAnimationFrame(runInputLoop);
}
function startInputLoop() {
if (!inputLoopTimer) {
runInputLoop();
}
}
function stopInputLoop() {
cancelAnimationFrame(inputLoopTimer);
inputLoopTimer = undefined;
}
function isGamepadConnected() {
var gamepads = navigator.getGamepads(); /* eslint-disable-line compat/compat */
for (var i = 0, len = gamepads.length; i < len; i++) {
var gamepad = gamepads[i];
if (gamepad && gamepad.connected) {
return true;
}
}
return false;
}
function onFocusOrGamepadAttach(e) {
/* eslint-disable-next-line compat/compat */
if (isGamepadConnected() && document.hasFocus()) {
console.log('Gamepad connected! Starting input loop');
startInputLoop();
}
}
function onFocusOrGamepadDetach(e) {
/* eslint-disable-next-line compat/compat */
if (!isGamepadConnected() || !document.hasFocus()) {
console.log('Gamepad disconnected! No other gamepads are connected, stopping input loop');
stopInputLoop();
} else {
console.log('Gamepad disconnected! There are gamepads still connected.');
}
}
// Event listeners for any change in gamepads' state.
window.addEventListener('gamepaddisconnected', onFocusOrGamepadDetach);
window.addEventListener('gamepadconnected', onFocusOrGamepadAttach);
window.addEventListener('blur', onFocusOrGamepadDetach);
window.addEventListener('focus', onFocusOrGamepadAttach);
onFocusOrGamepadAttach();
// The gamepadInputEmulation is a string property that exists in JavaScript UWAs and in WebViews in UWAs.
// It won't exist in Win8.1 style apps or browsers.
if (window.navigator && typeof window.navigator.gamepadInputEmulation === 'string') {
// We want the gamepad to provide gamepad VK keyboard events rather than moving a
// mouse like cursor. Set to "keyboard", the gamepad will provide such keyboard events
// and provide input to the DOM navigator.getGamepads API.
window.navigator.gamepadInputEmulation = 'gamepad';
}
});

View file

@ -3,72 +3,73 @@
import browser from 'browser';
export function getDeviceIcon(device) {
var baseUrl = "assets/img/devices/";
var baseUrl = 'assets/img/devices/';
switch (device.AppName || device.Client) {
case "Samsung Smart TV":
return baseUrl + "samsung.svg";
case "Xbox One":
return baseUrl + "xbox.svg";
case "Sony PS4":
return baseUrl + "playstation.svg";
case "Kodi":
return baseUrl + "kodi.svg";
case "Jellyfin Android":
return baseUrl + "android.svg";
case "Jellyfin Web":
case 'Samsung Smart TV':
return baseUrl + 'samsung.svg';
case 'Xbox One':
return baseUrl + 'xbox.svg';
case 'Sony PS4':
return baseUrl + 'playstation.svg';
case 'Kodi':
return baseUrl + 'kodi.svg';
case 'Jellyfin Android':
case 'Android TV':
return baseUrl + 'android.svg';
case 'Jellyfin Web':
switch (device.Name || device.DeviceName) {
case "Opera":
case "Opera TV":
case "Opera Android":
return baseUrl + "opera.svg";
case "Chrome":
case "Chrome Android":
return baseUrl + "chrome.svg";
case "Firefox":
case "Firefox Android":
return baseUrl + "firefox.svg";
case "Safari":
case "Safari iPad":
case "Safari iPhone":
return baseUrl + "safari.svg";
case "Edge":
return baseUrl + "edge.svg";
case "Internet Explorer":
return baseUrl + "msie.svg";
case 'Opera':
case 'Opera TV':
case 'Opera Android':
return baseUrl + 'opera.svg';
case 'Chrome':
case 'Chrome Android':
return baseUrl + 'chrome.svg';
case 'Firefox':
case 'Firefox Android':
return baseUrl + 'firefox.svg';
case 'Safari':
case 'Safari iPad':
case 'Safari iPhone':
return baseUrl + 'safari.svg';
case 'Edge':
return baseUrl + 'edge.svg';
case 'Internet Explorer':
return baseUrl + 'msie.svg';
default:
return baseUrl + "html5.svg";
return baseUrl + 'html5.svg';
}
default:
return baseUrl + "other.svg";
return baseUrl + 'other.svg';
}
}
export function getLibraryIcon(library) {
switch (library) {
case "movies":
return "video_library";
case "music":
return "library_music";
case "photos":
return "photo_library";
case "livetv":
return "live_tv";
case "tvshows":
return "tv";
case "trailers":
return "local_movies";
case "homevideos":
return "photo_library";
case "musicvideos":
return "music_video";
case "books":
return "library_books";
case "channels":
return "videocam";
case "playlists":
return "view_list";
case 'movies':
return 'video_library';
case 'music':
return 'library_music';
case 'photos':
return 'photo_library';
case 'livetv':
return 'live_tv';
case 'tvshows':
return 'tv';
case 'trailers':
return 'local_movies';
case 'homevideos':
return 'photo_library';
case 'musicvideos':
return 'music_video';
case 'books':
return 'library_books';
case 'channels':
return 'videocam';
case 'playlists':
return 'view_list';
default:
return "folder";
return 'folder';
}
}

View file

@ -1,44 +1,49 @@
define(['playbackManager', 'focusManager', 'appRouter', 'dom', 'apphost'], function (playbackManager, focusManager, appRouter, dom, appHost) {
'use strict';
import playbackManager from 'playbackManager';
import focusManager from 'focusManager';
import appRouter from 'appRouter';
import dom from 'dom';
import appHost from 'apphost';
var lastInputTime = new Date().getTime();
/* eslint-disable indent */
function notify() {
let lastInputTime = new Date().getTime();
export function notify() {
lastInputTime = new Date().getTime();
handleCommand('unknown');
}
function notifyMouseMove() {
export function notifyMouseMove() {
lastInputTime = new Date().getTime();
}
function idleTime() {
export function idleTime() {
return new Date().getTime() - lastInputTime;
}
function select(sourceElement) {
export function select(sourceElement) {
sourceElement.click();
}
var eventListenerCount = 0;
function on(scope, fn) {
let eventListenerCount = 0;
export function on(scope, fn) {
eventListenerCount++;
dom.addEventListener(scope, 'command', fn, {});
}
function off(scope, fn) {
export function off(scope, fn) {
if (eventListenerCount) {
eventListenerCount--;
}
dom.removeEventListener(scope, 'command', fn, {});
}
var commandTimes = {};
let commandTimes = {};
function checkCommandTime(command) {
var last = commandTimes[command] || 0;
var now = new Date().getTime();
const last = commandTimes[command] || 0;
const now = new Date().getTime();
if ((now - last) < 1000) {
return false;
@ -48,11 +53,11 @@ define(['playbackManager', 'focusManager', 'appRouter', 'dom', 'apphost'], funct
return true;
}
function handleCommand(name, options) {
export function handleCommand(commandName, options) {
lastInputTime = new Date().getTime();
var sourceElement = (options ? options.sourceElement : null);
let sourceElement = (options ? options.sourceElement : null);
if (sourceElement) {
sourceElement = focusManager.focusableParent(sourceElement);
@ -61,7 +66,7 @@ define(['playbackManager', 'focusManager', 'appRouter', 'dom', 'apphost'], funct
if (!sourceElement) {
sourceElement = document.activeElement || window;
var dlg = document.querySelector('.dialogContainer .dialog.opened');
const dlg = document.querySelector('.dialogContainer .dialog.opened');
if (dlg && (!sourceElement || !dlg.contains(sourceElement))) {
sourceElement = dlg;
@ -69,183 +74,182 @@ define(['playbackManager', 'focusManager', 'appRouter', 'dom', 'apphost'], funct
}
if (eventListenerCount) {
var customEvent = new CustomEvent("command", {
const customEvent = new CustomEvent('command', {
detail: {
command: name
command: commandName
},
bubbles: true,
cancelable: true
});
var eventResult = sourceElement.dispatchEvent(customEvent);
const eventResult = sourceElement.dispatchEvent(customEvent);
if (!eventResult) {
// event cancelled
return;
}
}
switch (name) {
case 'up':
const keyActions = (command) => ({
'up': () => {
focusManager.moveUp(sourceElement);
break;
case 'down':
},
'down': () => {
focusManager.moveDown(sourceElement);
break;
case 'left':
},
'left': () => {
focusManager.moveLeft(sourceElement);
break;
case 'right':
},
'right': () => {
focusManager.moveRight(sourceElement);
break;
case 'home':
},
'home': () => {
appRouter.goHome();
break;
case 'settings':
},
'settings': () => {
appRouter.showSettings();
break;
case 'back':
},
'back': () => {
if (appRouter.canGoBack()) {
appRouter.back();
} else if (appHost.supports('exit')) {
appHost.exit();
}
break;
case 'forward':
break;
case 'select':
},
'select': () => {
select(sourceElement);
break;
case 'pageup':
break;
case 'pagedown':
break;
case 'end':
break;
case 'menu':
break;
case 'info':
break;
case 'nextchapter':
},
'nextchapter': () => {
playbackManager.nextChapter();
break;
case 'next':
case 'nexttrack':
},
'next': () => {
playbackManager.nextTrack();
break;
case 'previous':
case 'previoustrack':
},
'nexttrack': () => {
playbackManager.nextTrack();
},
'previous': () => {
playbackManager.previousTrack();
break;
case 'previouschapter':
},
'previoustrack': () => {
playbackManager.previousTrack();
},
'previouschapter': () => {
playbackManager.previousChapter();
break;
case 'guide':
},
'guide': () => {
appRouter.showGuide();
break;
case 'recordedtv':
},
'recordedtv': () => {
appRouter.showRecordedTV();
break;
case 'record':
break;
case 'livetv':
},
'livetv': () => {
appRouter.showLiveTV();
break;
case 'mute':
},
'mute': () => {
playbackManager.setMute(true);
break;
case 'unmute':
},
'unmute': () => {
playbackManager.setMute(false);
break;
case 'togglemute':
},
'togglemute': () => {
playbackManager.toggleMute();
break;
case 'channelup':
},
'channelup': () => {
playbackManager.channelUp();
break;
case 'channeldown':
},
'channeldown': () => {
playbackManager.channelDown();
break;
case 'volumedown':
},
'volumedown': () => {
playbackManager.volumeDown();
break;
case 'volumeup':
},
'volumeup': () => {
playbackManager.volumeUp();
break;
case 'play':
},
'play': () => {
playbackManager.unpause();
break;
case 'pause':
},
'pause': () => {
playbackManager.pause();
break;
case 'playpause':
},
'playpause': () => {
playbackManager.playPause();
break;
case 'stop':
},
'stop': () => {
if (checkCommandTime('stop')) {
playbackManager.stop();
}
break;
case 'changezoom':
},
'changezoom': () => {
playbackManager.toggleAspectRatio();
break;
case 'changeaudiotrack':
},
'changeaudiotrack': () => {
playbackManager.changeAudioStream();
break;
case 'changesubtitletrack':
},
'changesubtitletrack': () => {
playbackManager.changeSubtitleStream();
break;
case 'search':
},
'search': () => {
appRouter.showSearch();
break;
case 'favorites':
},
'favorites': () => {
appRouter.showFavorites();
break;
case 'fastforward':
},
'fastforward': () => {
playbackManager.fastForward();
break;
case 'rewind':
},
'rewind': () => {
playbackManager.rewind();
break;
case 'togglefullscreen':
},
'togglefullscreen': () => {
playbackManager.toggleFullscreen();
break;
case 'disabledisplaymirror':
},
'disabledisplaymirror': () => {
playbackManager.enableDisplayMirroring(false);
break;
case 'enabledisplaymirror':
},
'enabledisplaymirror': () => {
playbackManager.enableDisplayMirroring(true);
break;
case 'toggledisplaymirror':
},
'toggledisplaymirror': () => {
playbackManager.toggleDisplayMirroring();
break;
case 'nowplaying':
},
'nowplaying': () => {
appRouter.showNowPlaying();
break;
case 'repeatnone':
},
'repeatnone': () => {
playbackManager.setRepeatMode('RepeatNone');
break;
case 'repeatall':
},
'repeatall': () => {
playbackManager.setRepeatMode('RepeatAll');
break;
case 'repeatone':
},
'repeatone': () => {
playbackManager.setRepeatMode('RepeatOne');
break;
default:
break;
}
})[command];
const action = keyActions(commandName);
if (action !== undefined) {
action.call();
} else {
console.debug(`inputManager: tried to process command with no action assigned: ${commandName}`);
}
}
// Alias for backward compatibility
export const trigger = handleCommand;
dom.addEventListener(document, 'click', notify, {
passive: true
});
return {
trigger: handleCommand,
handle: handleCommand,
notify: notify,
notifyMouseMove: notifyMouseMove,
idleTime: idleTime,
on: on,
off: off
};
});
/* eslint-enable indent */
export default {
trigger: handleCommand,
handle: handleCommand,
notify: notify,
notifyMouseMove: notifyMouseMove,
idleTime: idleTime,
on: on,
off: off
};

View file

@ -1,105 +1,105 @@
define(["connectionManager", "listView", "cardBuilder", "imageLoader", "libraryBrowser", "emby-itemscontainer", "emby-button"], function (connectionManager, listView, cardBuilder, imageLoader, libraryBrowser) {
"use strict";
define(['connectionManager', 'listView', 'cardBuilder', 'imageLoader', 'libraryBrowser', 'globalize', 'emby-itemscontainer', 'emby-button'], function (connectionManager, listView, cardBuilder, imageLoader, libraryBrowser, globalize) {
'use strict';
function renderItems(page, item) {
var sections = [];
if (item.ArtistCount) {
sections.push({
name: Globalize.translate("TabArtists"),
type: "MusicArtist"
name: globalize.translate('TabArtists'),
type: 'MusicArtist'
});
}
if (item.ProgramCount && "Person" == item.Type) {
if (item.ProgramCount && 'Person' == item.Type) {
sections.push({
name: Globalize.translate("HeaderUpcomingOnTV"),
type: "Program"
name: globalize.translate('HeaderUpcomingOnTV'),
type: 'Program'
});
}
if (item.MovieCount) {
sections.push({
name: Globalize.translate("TabMovies"),
type: "Movie"
name: globalize.translate('TabMovies'),
type: 'Movie'
});
}
if (item.SeriesCount) {
sections.push({
name: Globalize.translate("TabShows"),
type: "Series"
name: globalize.translate('TabShows'),
type: 'Series'
});
}
if (item.EpisodeCount) {
sections.push({
name: Globalize.translate("TabEpisodes"),
type: "Episode"
name: globalize.translate('TabEpisodes'),
type: 'Episode'
});
}
if (item.TrailerCount) {
sections.push({
name: Globalize.translate("TabTrailers"),
type: "Trailer"
name: globalize.translate('TabTrailers'),
type: 'Trailer'
});
}
if (item.AlbumCount) {
sections.push({
name: Globalize.translate("TabAlbums"),
type: "MusicAlbum"
name: globalize.translate('TabAlbums'),
type: 'MusicAlbum'
});
}
if (item.MusicVideoCount) {
sections.push({
name: Globalize.translate("TabMusicVideos"),
type: "MusicVideo"
name: globalize.translate('TabMusicVideos'),
type: 'MusicVideo'
});
}
var elem = page.querySelector("#childrenContent");
var elem = page.querySelector('#childrenContent');
elem.innerHTML = sections.map(function (section) {
var html = "";
var sectionClass = "verticalSection";
var html = '';
var sectionClass = 'verticalSection';
if ("Audio" === section.type) {
sectionClass += " verticalSection-extrabottompadding";
if ('Audio' === section.type) {
sectionClass += ' verticalSection-extrabottompadding';
}
html += '<div class="' + sectionClass + '" data-type="' + section.type + '">';
html += '<div class="sectionTitleContainer sectionTitleContainer-cards">';
html += '<h2 class="sectionTitle sectionTitle-cards padded-left">';
html += section.name;
html += "</h2>";
html += '<a is="emby-linkbutton" href="#" class="clearLink hide" style="margin-left:1em;vertical-align:middle;"><button is="emby-button" type="button" class="raised more raised-mini noIcon">' + Globalize.translate("ButtonMore") + "</button></a>";
html += "</div>";
html += '</h2>';
html += '<a is="emby-linkbutton" href="#" class="clearLink hide" style="margin-left:1em;vertical-align:middle;"><button is="emby-button" type="button" class="raised more raised-mini noIcon">' + globalize.translate('ButtonMore') + '</button></a>';
html += '</div>';
html += '<div is="emby-itemscontainer" class="itemsContainer padded-left padded-right">';
html += "</div>";
return html += "</div>";
}).join("");
var sectionElems = elem.querySelectorAll(".verticalSection");
html += '</div>';
return html += '</div>';
}).join('');
var sectionElems = elem.querySelectorAll('.verticalSection');
for (var i = 0, length = sectionElems.length; i < length; i++) {
renderSection(page, item, sectionElems[i], sectionElems[i].getAttribute("data-type"));
renderSection(page, item, sectionElems[i], sectionElems[i].getAttribute('data-type'));
}
}
function renderSection(page, item, element, type) {
switch (type) {
case "Program":
case 'Program':
loadItems(element, item, type, {
MediaTypes: "",
IncludeItemTypes: "Program",
PersonTypes: "",
ArtistIds: "",
AlbumArtistIds: "",
MediaTypes: '',
IncludeItemTypes: 'Program',
PersonTypes: '',
ArtistIds: '',
AlbumArtistIds: '',
Limit: 10,
SortBy: "StartDate"
SortBy: 'StartDate'
}, {
shape: "overflowBackdrop",
shape: 'overflowBackdrop',
showTitle: true,
centerText: true,
overlayMoreButton: true,
@ -111,17 +111,17 @@ define(["connectionManager", "listView", "cardBuilder", "imageLoader", "libraryB
});
break;
case "Movie":
case 'Movie':
loadItems(element, item, type, {
MediaTypes: "",
IncludeItemTypes: "Movie",
PersonTypes: "",
ArtistIds: "",
AlbumArtistIds: "",
MediaTypes: '',
IncludeItemTypes: 'Movie',
PersonTypes: '',
ArtistIds: '',
AlbumArtistIds: '',
Limit: 10,
SortBy: "SortName"
SortBy: 'SortName'
}, {
shape: "overflowPortrait",
shape: 'overflowPortrait',
showTitle: true,
centerText: true,
overlayMoreButton: true,
@ -130,68 +130,68 @@ define(["connectionManager", "listView", "cardBuilder", "imageLoader", "libraryB
});
break;
case "MusicVideo":
case 'MusicVideo':
loadItems(element, item, type, {
MediaTypes: "",
IncludeItemTypes: "MusicVideo",
PersonTypes: "",
ArtistIds: "",
AlbumArtistIds: "",
MediaTypes: '',
IncludeItemTypes: 'MusicVideo',
PersonTypes: '',
ArtistIds: '',
AlbumArtistIds: '',
Limit: 10,
SortBy: "SortName"
SortBy: 'SortName'
}, {
shape: "overflowPortrait",
shape: 'overflowPortrait',
showTitle: true,
centerText: true,
overlayPlayButton: true
});
break;
case "Trailer":
case 'Trailer':
loadItems(element, item, type, {
MediaTypes: "",
IncludeItemTypes: "Trailer",
PersonTypes: "",
ArtistIds: "",
AlbumArtistIds: "",
MediaTypes: '',
IncludeItemTypes: 'Trailer',
PersonTypes: '',
ArtistIds: '',
AlbumArtistIds: '',
Limit: 10,
SortBy: "SortName"
SortBy: 'SortName'
}, {
shape: "overflowPortrait",
shape: 'overflowPortrait',
showTitle: true,
centerText: true,
overlayPlayButton: true
});
break;
case "Series":
case 'Series':
loadItems(element, item, type, {
MediaTypes: "",
IncludeItemTypes: "Series",
PersonTypes: "",
ArtistIds: "",
AlbumArtistIds: "",
MediaTypes: '',
IncludeItemTypes: 'Series',
PersonTypes: '',
ArtistIds: '',
AlbumArtistIds: '',
Limit: 10,
SortBy: "SortName"
SortBy: 'SortName'
}, {
shape: "overflowPortrait",
shape: 'overflowPortrait',
showTitle: true,
centerText: true,
overlayMoreButton: true
});
break;
case "MusicAlbum":
case 'MusicAlbum':
loadItems(element, item, type, {
MediaTypes: "",
IncludeItemTypes: "MusicAlbum",
PersonTypes: "",
ArtistIds: "",
AlbumArtistIds: "",
SortOrder: "Descending",
SortBy: "ProductionYear,Sortname"
MediaTypes: '',
IncludeItemTypes: 'MusicAlbum',
PersonTypes: '',
ArtistIds: '',
AlbumArtistIds: '',
SortOrder: 'Descending',
SortBy: 'ProductionYear,Sortname'
}, {
shape: "overflowSquare",
shape: 'overflowSquare',
playFromHere: true,
showTitle: true,
showYear: true,
@ -201,17 +201,17 @@ define(["connectionManager", "listView", "cardBuilder", "imageLoader", "libraryB
});
break;
case "MusicArtist":
case 'MusicArtist':
loadItems(element, item, type, {
MediaTypes: "",
IncludeItemTypes: "MusicArtist",
PersonTypes: "",
ArtistIds: "",
AlbumArtistIds: "",
MediaTypes: '',
IncludeItemTypes: 'MusicArtist',
PersonTypes: '',
ArtistIds: '',
AlbumArtistIds: '',
Limit: 8,
SortBy: "SortName"
SortBy: 'SortName'
}, {
shape: "overflowSquare",
shape: 'overflowSquare',
playFromHere: true,
showTitle: true,
showParentTitle: true,
@ -221,17 +221,17 @@ define(["connectionManager", "listView", "cardBuilder", "imageLoader", "libraryB
});
break;
case "Episode":
case 'Episode':
loadItems(element, item, type, {
MediaTypes: "",
IncludeItemTypes: "Episode",
PersonTypes: "",
ArtistIds: "",
AlbumArtistIds: "",
MediaTypes: '',
IncludeItemTypes: 'Episode',
PersonTypes: '',
ArtistIds: '',
AlbumArtistIds: '',
Limit: 6,
SortBy: "SortName"
SortBy: 'SortName'
}, {
shape: "overflowBackdrop",
shape: 'overflowBackdrop',
showTitle: true,
showParentTitle: true,
centerText: true,
@ -239,17 +239,17 @@ define(["connectionManager", "listView", "cardBuilder", "imageLoader", "libraryB
});
break;
case "Audio":
case 'Audio':
loadItems(element, item, type, {
MediaTypes: "",
IncludeItemTypes: "Audio",
PersonTypes: "",
ArtistIds: "",
AlbumArtistIds: "",
SortBy: "AlbumArtist,Album,SortName"
MediaTypes: '',
IncludeItemTypes: 'Audio',
PersonTypes: '',
ArtistIds: '',
AlbumArtistIds: '',
SortBy: 'AlbumArtist,Album,SortName'
}, {
playFromHere: true,
action: "playallfromhere",
action: 'playallfromhere',
smallIcon: true,
artist: true
});
@ -259,27 +259,27 @@ define(["connectionManager", "listView", "cardBuilder", "imageLoader", "libraryB
function loadItems(element, item, type, query, listOptions) {
query = getQuery(query, item);
getItemsFunction(query, item)(query.StartIndex, query.Limit, query.Fields).then(function (result) {
var html = "";
var html = '';
if (query.Limit && result.TotalRecordCount > query.Limit) {
var link = element.querySelector("a");
link.classList.remove("hide");
link.setAttribute("href", getMoreItemsHref(item, type));
var link = element.querySelector('a');
link.classList.remove('hide');
link.setAttribute('href', getMoreItemsHref(item, type));
} else {
element.querySelector("a").classList.add("hide");
element.querySelector('a').classList.add('hide');
}
listOptions.items = result.Items;
var itemsContainer = element.querySelector(".itemsContainer");
var itemsContainer = element.querySelector('.itemsContainer');
if ("Audio" == type) {
if ('Audio' == type) {
html = listView.getListViewHtml(listOptions);
itemsContainer.classList.remove("vertical-wrap");
itemsContainer.classList.add("vertical-list");
itemsContainer.classList.remove('vertical-wrap');
itemsContainer.classList.add('vertical-list');
} else {
html = cardBuilder.getCardsHtml(listOptions);
itemsContainer.classList.add("vertical-wrap");
itemsContainer.classList.remove("vertical-list");
itemsContainer.classList.add('vertical-wrap');
itemsContainer.classList.remove('vertical-list');
}
itemsContainer.innerHTML = html;
@ -288,51 +288,51 @@ define(["connectionManager", "listView", "cardBuilder", "imageLoader", "libraryB
}
function getMoreItemsHref(item, type) {
if ("Genre" == item.Type) {
return "list.html?type=" + type + "&genreId=" + item.Id + "&serverId=" + item.ServerId;
if ('Genre' == item.Type) {
return 'list.html?type=' + type + '&genreId=' + item.Id + '&serverId=' + item.ServerId;
}
if ("MusicGenre" == item.Type) {
return "list.html?type=" + type + "&musicGenreId=" + item.Id + "&serverId=" + item.ServerId;
if ('MusicGenre' == item.Type) {
return 'list.html?type=' + type + '&musicGenreId=' + item.Id + '&serverId=' + item.ServerId;
}
if ("Studio" == item.Type) {
return "list.html?type=" + type + "&studioId=" + item.Id + "&serverId=" + item.ServerId;
if ('Studio' == item.Type) {
return 'list.html?type=' + type + '&studioId=' + item.Id + '&serverId=' + item.ServerId;
}
if ("MusicArtist" == item.Type) {
return "list.html?type=" + type + "&artistId=" + item.Id + "&serverId=" + item.ServerId;
if ('MusicArtist' == item.Type) {
return 'list.html?type=' + type + '&artistId=' + item.Id + '&serverId=' + item.ServerId;
}
if ("Person" == item.Type) {
return "list.html?type=" + type + "&personId=" + item.Id + "&serverId=" + item.ServerId;
if ('Person' == item.Type) {
return 'list.html?type=' + type + '&personId=' + item.Id + '&serverId=' + item.ServerId;
}
return "list.html?type=" + type + "&parentId=" + item.Id + "&serverId=" + item.ServerId;
return 'list.html?type=' + type + '&parentId=' + item.Id + '&serverId=' + item.ServerId;
}
function addCurrentItemToQuery(query, item) {
if (item.Type == "Person") {
if (item.Type == 'Person') {
query.PersonIds = item.Id;
} else if (item.Type == "Genre") {
} else if (item.Type == 'Genre') {
query.Genres = item.Name;
} else if (item.Type == "MusicGenre") {
} else if (item.Type == 'MusicGenre') {
query.Genres = item.Name;
} else if (item.Type == "GameGenre") {
} else if (item.Type == 'GameGenre') {
query.Genres = item.Name;
} else if (item.Type == "Studio") {
} else if (item.Type == 'Studio') {
query.StudioIds = item.Id;
} else if (item.Type == "MusicArtist") {
} else if (item.Type == 'MusicArtist') {
query.AlbumArtistIds = item.Id;
}
}
function getQuery(options, item) {
var query = {
SortOrder: "Ascending",
IncludeItemTypes: "",
SortOrder: 'Ascending',
IncludeItemTypes: '',
Recursive: true,
Fields: "AudioInfo,SeriesInfo,ParentId,PrimaryImageAspectRatio,BasicSyncInfo",
Fields: 'AudioInfo,SeriesInfo,ParentId,PrimaryImageAspectRatio,BasicSyncInfo',
Limit: 100,
StartIndex: 0,
CollapseBoxSetItems: false
@ -349,12 +349,12 @@ define(["connectionManager", "listView", "cardBuilder", "imageLoader", "libraryB
query.Limit = limit;
if (fields) {
query.Fields += "," + fields;
query.Fields += ',' + fields;
}
var apiClient = connectionManager.getApiClient(item.ServerId);
if ("MusicArtist" === query.IncludeItemTypes) {
if ('MusicArtist' === query.IncludeItemTypes) {
query.IncludeItemTypes = null;
return apiClient.getAlbumArtists(apiClient.getCurrentUserId(), query);
}

View file

@ -0,0 +1,170 @@
/**
* Module for performing keyboard navigation.
* @module components/input/keyboardnavigation
*/
import inputManager from 'inputManager';
import layoutManager from 'layoutManager';
/**
* Key name mapping.
*/
const KeyNames = {
13: 'Enter',
19: 'Pause',
27: 'Escape',
32: 'Space',
37: 'ArrowLeft',
38: 'ArrowUp',
39: 'ArrowRight',
40: 'ArrowDown',
// MediaRewind (Tizen/WebOS)
412: 'MediaRewind',
// MediaStop (Tizen/WebOS)
413: 'MediaStop',
// MediaPlay (Tizen/WebOS)
415: 'MediaPlay',
// MediaFastForward (Tizen/WebOS)
417: 'MediaFastForward',
// Back (WebOS)
461: 'Back',
// Back (Tizen)
10009: 'Back',
// MediaTrackPrevious (Tizen)
10232: 'MediaTrackPrevious',
// MediaTrackNext (Tizen)
10233: 'MediaTrackNext',
// MediaPlayPause (Tizen)
10252: 'MediaPlayPause'
};
/**
* Keys used for keyboard navigation.
*/
const NavigationKeys = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'];
let hasFieldKey = false;
try {
hasFieldKey = 'key' in new KeyboardEvent('keydown');
} catch (e) {
console.error("error checking 'key' field");
}
if (!hasFieldKey) {
// Add [a..z]
for (let i = 65; i <= 90; i++) {
KeyNames[i] = String.fromCharCode(i).toLowerCase();
}
}
/**
* Returns key name from event.
*
* @param {KeyboardEvent} event - Keyboard event.
* @return {string} Key name.
*/
export function getKeyName(event) {
return KeyNames[event.keyCode] || event.key;
}
/**
* Returns _true_ if key is used for navigation.
*
* @param {string} key - Key name.
* @return {boolean} _true_ if key is used for navigation.
*/
export function isNavigationKey(key) {
return NavigationKeys.indexOf(key) != -1;
}
export function enable() {
document.addEventListener('keydown', function (e) {
const key = getKeyName(e);
// Ignore navigation keys for non-TV
if (!layoutManager.tv && isNavigationKey(key)) {
return;
}
let capture = true;
switch (key) {
case 'ArrowLeft':
inputManager.handle('left');
break;
case 'ArrowUp':
inputManager.handle('up');
break;
case 'ArrowRight':
inputManager.handle('right');
break;
case 'ArrowDown':
inputManager.handle('down');
break;
case 'Back':
inputManager.handle('back');
break;
case 'Escape':
if (layoutManager.tv) {
inputManager.handle('back');
} else {
capture = false;
}
break;
case 'MediaPlay':
inputManager.handle('play');
break;
case 'Pause':
inputManager.handle('pause');
break;
case 'MediaPlayPause':
inputManager.handle('playpause');
break;
case 'MediaRewind':
inputManager.handle('rewind');
break;
case 'MediaFastForward':
inputManager.handle('fastforward');
break;
case 'MediaStop':
inputManager.handle('stop');
break;
case 'MediaTrackPrevious':
inputManager.handle('previoustrack');
break;
case 'MediaTrackNext':
inputManager.handle('nexttrack');
break;
default:
capture = false;
}
if (capture) {
console.debug('disabling default event handling');
e.preventDefault();
}
});
}
// Gamepad initialisation. No script is required if no gamepads are present at init time, saving a bit of resources.
// Whenever the gamepad is connected, we hand all the control of the gamepad to gamepadtokey.js by removing the event handler
function attachGamepadScript(e) {
console.log('Gamepad connected! Attaching gamepadtokey.js script');
window.removeEventListener('gamepadconnected', attachGamepadScript);
require(['scripts/gamepadtokey']);
}
// No need to check for gamepads manually at load time, the eventhandler will be fired for that
if (navigator.getGamepads) { /* eslint-disable-line compat/compat */
window.addEventListener('gamepadconnected', attachGamepadScript);
}
export default {
enable: enable,
getKeyName: getKeyName,
isNavigationKey: isNavigationKey
};

View file

@ -1,9 +1,9 @@
define(["userSettings"], function (userSettings) {
"use strict";
define(['userSettings', 'globalize'], function (userSettings, globalize) {
'use strict';
var libraryBrowser = {
getSavedQueryKey: function (modifier) {
return window.location.href.split("#")[0] + (modifier || "");
return window.location.href.split('#')[0] + (modifier || '');
},
loadSavedQueryValues: function (key, query) {
var values = userSettings.get(key);
@ -29,34 +29,34 @@ define(["userSettings"], function (userSettings) {
userSettings.set(key, JSON.stringify(values));
},
saveViewSetting: function (key, value) {
userSettings.set(key + "-_view", value);
userSettings.set(key + '-_view', value);
},
getSavedView: function (key) {
return userSettings.get(key + "-_view");
return userSettings.get(key + '-_view');
},
showLayoutMenu: function (button, currentLayout, views) {
var dispatchEvent = true;
if (!views) {
dispatchEvent = false;
views = button.getAttribute("data-layouts");
views = views ? views.split(",") : ["List", "Poster", "PosterCard", "Thumb", "ThumbCard"];
views = button.getAttribute('data-layouts');
views = views ? views.split(',') : ['List', 'Poster', 'PosterCard', 'Thumb', 'ThumbCard'];
}
var menuItems = views.map(function (v) {
return {
name: Globalize.translate("Option" + v),
name: globalize.translate('Option' + v),
id: v,
selected: currentLayout == v
};
});
require(["actionsheet"], function (actionsheet) {
require(['actionsheet'], function (actionsheet) {
actionsheet.show({
items: menuItems,
positionTo: button,
callback: function (id) {
button.dispatchEvent(new CustomEvent("layoutchange", {
button.dispatchEvent(new CustomEvent('layoutchange', {
detail: {
viewStyle: id
},
@ -66,7 +66,7 @@ define(["userSettings"], function (userSettings) {
if (!dispatchEvent) {
if (window.$) {
$(button).trigger("layoutchange", [id]);
$(button).trigger('layoutchange', [id]);
}
}
}
@ -77,49 +77,49 @@ define(["userSettings"], function (userSettings) {
var startIndex = options.startIndex;
var limit = options.limit;
var totalRecordCount = options.totalRecordCount;
var html = "";
var html = '';
var recordsEnd = Math.min(startIndex + limit, totalRecordCount);
var showControls = limit < totalRecordCount;
if (html += '<div class="listPaging">', showControls) {
html += '<span style="vertical-align:middle;">';
html += Globalize.translate("ListPaging", (totalRecordCount ? startIndex + 1 : 0), recordsEnd, totalRecordCount);
html += "</span>";
html += globalize.translate('ListPaging', (totalRecordCount ? startIndex + 1 : 0), recordsEnd, totalRecordCount);
html += '</span>';
}
if (showControls || options.viewButton || options.filterButton || options.sortButton || options.addLayoutButton) {
html += '<div style="display:inline-block;">';
if (showControls) {
html += '<button is="paper-icon-button-light" class="btnPreviousPage autoSize" ' + (startIndex ? "" : "disabled") + '><i class="material-icons arrow_back"></i></button>';
html += '<button is="paper-icon-button-light" class="btnNextPage autoSize" ' + (startIndex + limit >= totalRecordCount ? "disabled" : "") + '><i class="material-icons arrow_forward"></i></button>';
html += '<button is="paper-icon-button-light" class="btnPreviousPage autoSize" ' + (startIndex ? '' : 'disabled') + '><span class="material-icons arrow_back"></span></button>';
html += '<button is="paper-icon-button-light" class="btnNextPage autoSize" ' + (startIndex + limit >= totalRecordCount ? 'disabled' : '') + '><span class="material-icons arrow_forward"></span></button>';
}
if (options.addLayoutButton) {
html += '<button is="paper-icon-button-light" title="' + Globalize.translate("ButtonSelectView") + '" class="btnChangeLayout autoSize" data-layouts="' + (options.layouts || "") + '" onclick="LibraryBrowser.showLayoutMenu(this, \'' + (options.currentLayout || "") + '\');"><i class="material-icons view_comfy"></i></button>';
html += '<button is="paper-icon-button-light" title="' + globalize.translate('ButtonSelectView') + '" class="btnChangeLayout autoSize" data-layouts="' + (options.layouts || '') + '" onclick="LibraryBrowser.showLayoutMenu(this, \'' + (options.currentLayout || '') + '\');"><span class="material-icons view_comfy"></span></button>';
}
if (options.sortButton) {
html += '<button is="paper-icon-button-light" class="btnSort autoSize" title="' + Globalize.translate("ButtonSort") + '"><i class="material-icons sort_by_alpha"></i></button>';
html += '<button is="paper-icon-button-light" class="btnSort autoSize" title="' + globalize.translate('ButtonSort') + '"><span class="material-icons sort_by_alpha"></span></button>';
}
if (options.filterButton) {
html += '<button is="paper-icon-button-light" class="btnFilter autoSize" title="' + Globalize.translate("ButtonFilter") + '"><i class="material-icons filter_list"></i></button>';
html += '<button is="paper-icon-button-light" class="btnFilter autoSize" title="' + globalize.translate('ButtonFilter') + '"><span class="material-icons filter_list"></span></button>';
}
html += "</div>";
html += '</div>';
}
return html += "</div>";
return html += '</div>';
},
showSortMenu: function (options) {
require(["dialogHelper", "emby-radio"], function (dialogHelper) {
require(['dialogHelper', 'emby-radio'], function (dialogHelper) {
function onSortByChange() {
var newValue = this.value;
if (this.checked) {
var changed = options.query.SortBy != newValue;
options.query.SortBy = newValue.replace("_", ",");
options.query.SortBy = newValue.replace('_', ',');
options.query.StartIndex = 0;
if (options.callback && changed) {
@ -148,48 +148,48 @@ define(["userSettings"], function (userSettings) {
entryAnimationDuration: 160,
exitAnimationDuration: 200
});
dlg.classList.add("ui-body-a");
dlg.classList.add("background-theme-a");
dlg.classList.add("formDialog");
var html = "";
dlg.classList.add('ui-body-a');
dlg.classList.add('background-theme-a');
dlg.classList.add('formDialog');
var html = '';
html += '<div style="margin:0;padding:1.25em 1.5em 1.5em;">';
html += '<h2 style="margin:0 0 .5em;">';
html += Globalize.translate("HeaderSortBy");
html += "</h2>";
html += globalize.translate('HeaderSortBy');
html += '</h2>';
var i;
var length;
var isChecked;
html += '<div>';
for (i = 0, length = options.items.length; i < length; i++) {
var option = options.items[i];
var radioValue = option.id.replace(",", "_");
isChecked = (options.query.SortBy || "").replace(",", "_") == radioValue ? " checked" : "";
html += '<label class="radio-label-block"><input type="radio" is="emby-radio" name="SortBy" data-id="' + option.id + '" value="' + radioValue + '" class="menuSortBy" ' + isChecked + " /><span>" + option.name + "</span></label>";
var radioValue = option.id.replace(',', '_');
isChecked = (options.query.SortBy || '').replace(',', '_') == radioValue ? ' checked' : '';
html += '<label class="radio-label-block"><input type="radio" is="emby-radio" name="SortBy" data-id="' + option.id + '" value="' + radioValue + '" class="menuSortBy" ' + isChecked + ' /><span>' + option.name + '</span></label>';
}
html += "</div>";
html += '</div>';
html += '<h2 style="margin: 1em 0 .5em;">';
html += Globalize.translate("HeaderSortOrder");
html += "</h2>";
html += "<div>";
isChecked = "Ascending" == options.query.SortOrder ? " checked" : "";
html += '<label class="radio-label-block"><input type="radio" is="emby-radio" name="SortOrder" value="Ascending" class="menuSortOrder" ' + isChecked + " /><span>" + Globalize.translate("OptionAscending") + "</span></label>";
isChecked = "Descending" == options.query.SortOrder ? " checked" : "";
html += '<label class="radio-label-block"><input type="radio" is="emby-radio" name="SortOrder" value="Descending" class="menuSortOrder" ' + isChecked + " /><span>" + Globalize.translate("OptionDescending") + "</span></label>";
html += "</div>";
html += "</div>";
html += globalize.translate('HeaderSortOrder');
html += '</h2>';
html += '<div>';
isChecked = 'Ascending' == options.query.SortOrder ? ' checked' : '';
html += '<label class="radio-label-block"><input type="radio" is="emby-radio" name="SortOrder" value="Ascending" class="menuSortOrder" ' + isChecked + ' /><span>' + globalize.translate('OptionAscending') + '</span></label>';
isChecked = 'Descending' == options.query.SortOrder ? ' checked' : '';
html += '<label class="radio-label-block"><input type="radio" is="emby-radio" name="SortOrder" value="Descending" class="menuSortOrder" ' + isChecked + ' /><span>' + globalize.translate('OptionDescending') + '</span></label>';
html += '</div>';
html += '</div>';
dlg.innerHTML = html;
dialogHelper.open(dlg);
var sortBys = dlg.querySelectorAll(".menuSortBy");
var sortBys = dlg.querySelectorAll('.menuSortBy');
for (i = 0, length = sortBys.length; i < length; i++) {
sortBys[i].addEventListener("change", onSortByChange);
sortBys[i].addEventListener('change', onSortByChange);
}
var sortOrders = dlg.querySelectorAll(".menuSortOrder");
var sortOrders = dlg.querySelectorAll('.menuSortOrder');
for (i = 0, length = sortOrders.length; i < length; i++) {
sortOrders[i].addEventListener("change", onSortOrderChange);
sortOrders[i].addEventListener('change', onSortOrderChange);
}
});
}

File diff suppressed because it is too large Load diff

View file

@ -1,12 +1,12 @@
define(["layoutManager", "datetime", "cardBuilder", "apphost"], function (layoutManager, datetime, cardBuilder, appHost) {
"use strict";
define(['layoutManager', 'datetime', 'cardBuilder', 'apphost'], function (layoutManager, datetime, cardBuilder, appHost) {
'use strict';
function enableScrollX() {
return !layoutManager.desktop;
}
function getBackdropShape() {
return enableScrollX() ? "overflowBackdrop" : "backdrop";
return enableScrollX() ? 'overflowBackdrop' : 'backdrop';
}
function getTimersHtml(timers, options) {
@ -14,27 +14,27 @@ define(["layoutManager", "datetime", "cardBuilder", "apphost"], function (layout
var i;
var length;
var items = timers.map(function (t) {
t.Type = "Timer";
t.Type = 'Timer';
return t;
});
var groups = [];
var currentGroupName = "";
var currentGroupName = '';
var currentGroup = [];
for (i = 0, length = items.length; i < length; i++) {
var item = items[i];
var dateText = "";
var dateText = '';
if (options.indexByDate !== false && item.StartDate) {
try {
var premiereDate = datetime.parseISO8601Date(item.StartDate, true);
dateText = datetime.toLocaleDateString(premiereDate, {
weekday: "long",
month: "short",
day: "numeric"
weekday: 'long',
month: 'short',
day: 'numeric'
});
} catch (err) {
console.error("error parsing premiereDate:" + item.StartDate + "; error: " + err);
console.error('error parsing premiereDate:' + item.StartDate + '; error: ' + err);
}
}
@ -60,23 +60,23 @@ define(["layoutManager", "datetime", "cardBuilder", "apphost"], function (layout
});
}
var html = "";
var html = '';
for (i = 0, length = groups.length; i < length; i++) {
var group = groups[i];
var supportsImageAnalysis = appHost.supports("imageanalysis");
var supportsImageAnalysis = appHost.supports('imageanalysis');
var cardLayout = appHost.preferVisualCards || supportsImageAnalysis;
cardLayout = true;
if (group.name) {
html += '<div class="verticalSection">';
html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + group.name + "</h2>";
html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + group.name + '</h2>';
}
if (enableScrollX()) {
var scrollXClass = "scrollX hiddenScrollX";
var scrollXClass = 'scrollX hiddenScrollX';
if (layoutManager.tv) {
scrollXClass += " smoothScrollX";
scrollXClass += ' smoothScrollX';
}
html += '<div is="emby-itemscontainer" class="itemsContainer ' + scrollXClass + ' padded-left padded-right">';
@ -86,26 +86,26 @@ define(["layoutManager", "datetime", "cardBuilder", "apphost"], function (layout
html += cardBuilder.getCardsHtml({
items: group.items,
shape: cardLayout ? getBackdropShape() : enableScrollX() ? "autoOverflow" : "autoVertical",
shape: cardLayout ? getBackdropShape() : enableScrollX() ? 'autoOverflow' : 'autoVertical',
showParentTitleOrTitle: true,
showAirTime: true,
showAirEndTime: true,
showChannelName: !cardLayout,
cardLayout: cardLayout,
centerText: !cardLayout,
action: "edit",
cardFooterAside: "none",
preferThumb: !!cardLayout || "auto",
defaultShape: cardLayout ? null : "portrait",
action: 'edit',
cardFooterAside: 'none',
preferThumb: !!cardLayout || 'auto',
defaultShape: cardLayout ? null : 'portrait',
coverImage: true,
allowBottomPadding: false,
overlayText: false,
showChannelLogo: cardLayout
});
html += "</div>";
html += '</div>';
if (group.name) {
html += "</div>";
html += '</div>';
}
}

169
src/scripts/mouseManager.js Normal file
View file

@ -0,0 +1,169 @@
define(['inputManager', 'focusManager', 'browser', 'layoutManager', 'events', 'dom'], function (inputManager, focusManager, browser, layoutManager, events, dom) {
'use strict';
var self = {};
var lastMouseInputTime = new Date().getTime();
var isMouseIdle;
function mouseIdleTime() {
return new Date().getTime() - lastMouseInputTime;
}
function notifyApp() {
inputManager.notifyMouseMove();
}
function removeIdleClasses() {
var classList = document.body.classList;
classList.remove('mouseIdle');
classList.remove('mouseIdle-tv');
}
function addIdleClasses() {
var classList = document.body.classList;
classList.add('mouseIdle');
if (layoutManager.tv) {
classList.add('mouseIdle-tv');
}
}
var lastPointerMoveData;
function onPointerMove(e) {
var eventX = e.screenX;
var eventY = e.screenY;
// if coord don't exist how could it move
if (typeof eventX === 'undefined' && typeof eventY === 'undefined') {
return;
}
var obj = lastPointerMoveData;
if (!obj) {
lastPointerMoveData = {
x: eventX,
y: eventY
};
return;
}
// if coord are same, it didn't move
if (Math.abs(eventX - obj.x) < 10 && Math.abs(eventY - obj.y) < 10) {
return;
}
obj.x = eventX;
obj.y = eventY;
lastMouseInputTime = new Date().getTime();
notifyApp();
if (isMouseIdle) {
isMouseIdle = false;
removeIdleClasses();
events.trigger(self, 'mouseactive');
}
}
function onPointerEnter(e) {
var pointerType = e.pointerType || (layoutManager.mobile ? 'touch' : 'mouse');
if (pointerType === 'mouse') {
if (!isMouseIdle) {
var parent = focusManager.focusableParent(e.target);
if (parent) {
focusManager.focus(parent);
}
}
}
}
function enableFocusWithMouse() {
if (!layoutManager.tv) {
return false;
}
if (browser.web0s) {
return false;
}
if (browser.tv) {
return true;
}
return false;
}
function onMouseInterval() {
if (!isMouseIdle && mouseIdleTime() >= 5000) {
isMouseIdle = true;
addIdleClasses();
events.trigger(self, 'mouseidle');
}
}
var mouseInterval;
function startMouseInterval() {
if (!mouseInterval) {
mouseInterval = setInterval(onMouseInterval, 5000);
}
}
function stopMouseInterval() {
var interval = mouseInterval;
if (interval) {
clearInterval(interval);
mouseInterval = null;
}
removeIdleClasses();
}
function initMouse() {
stopMouseInterval();
dom.removeEventListener(document, (window.PointerEvent ? 'pointermove' : 'mousemove'), onPointerMove, {
passive: true
});
if (!layoutManager.mobile) {
startMouseInterval();
dom.addEventListener(document, (window.PointerEvent ? 'pointermove' : 'mousemove'), onPointerMove, {
passive: true
});
}
dom.removeEventListener(document, (window.PointerEvent ? 'pointerenter' : 'mouseenter'), onPointerEnter, {
capture: true,
passive: true
});
if (enableFocusWithMouse()) {
dom.addEventListener(document, (window.PointerEvent ? 'pointerenter' : 'mouseenter'), onPointerEnter, {
capture: true,
passive: true
});
}
}
initMouse();
events.on(layoutManager, 'modechange', initMouse);
return self;
});

View file

@ -1,14 +1,14 @@
define(["listView"], function (listView) {
"use strict";
define(['listView'], function (listView) {
'use strict';
function getFetchPlaylistItemsFn(itemId) {
return function () {
var query = {
Fields: "PrimaryImageAspectRatio,UserData",
EnableImageTypes: "Primary,Backdrop,Banner,Thumb",
Fields: 'PrimaryImageAspectRatio,UserData',
EnableImageTypes: 'Primary,Backdrop,Banner,Thumb',
UserId: ApiClient.getCurrentUserId()
};
return ApiClient.getJSON(ApiClient.getUrl("Playlists/" + itemId + "/Items", query));
return ApiClient.getJSON(ApiClient.getUrl(`Playlists/${itemId}/Items`, query));
};
}
@ -19,7 +19,7 @@ define(["listView"], function (listView) {
showIndex: false,
showRemoveFromPlaylist: true,
playFromHere: true,
action: "playallfromhere",
action: 'playallfromhere',
smallIcon: true,
dragHandle: true,
playlistId: itemId
@ -28,9 +28,9 @@ define(["listView"], function (listView) {
}
function init(page, item) {
var elem = page.querySelector("#childrenContent .itemsContainer");
elem.classList.add("vertical-list");
elem.classList.remove("vertical-wrap");
var elem = page.querySelector('#childrenContent .itemsContainer');
elem.classList.add('vertical-list');
elem.classList.remove('vertical-wrap');
elem.enableDragReordering(true);
elem.fetchData = getFetchPlaylistItemsFn(item.Id);
elem.getItemsHtml = getItemsHtmlFn(item.Id);
@ -43,8 +43,8 @@ define(["listView"], function (listView) {
init(page, item);
}
page.querySelector("#childrenContent").classList.add("verticalSection-extrabottompadding");
page.querySelector("#childrenContent .itemsContainer").refreshItems();
page.querySelector('#childrenContent').classList.add('verticalSection-extrabottompadding');
page.querySelector('#childrenContent .itemsContainer').refreshItems();
}
};
});

View file

@ -1,5 +1,5 @@
define(["loading", "listView", "cardBuilder", "libraryMenu", "libraryBrowser", "apphost", "imageLoader", "emby-itemscontainer"], function (loading, listView, cardBuilder, libraryMenu, libraryBrowser, appHost, imageLoader) {
"use strict";
define(['loading', 'listView', 'cardBuilder', 'libraryMenu', 'libraryBrowser', 'apphost', 'imageLoader', 'userSettings', 'emby-itemscontainer'], function (loading, listView, cardBuilder, libraryMenu, libraryBrowser, appHost, imageLoader, userSettings) {
'use strict';
return function (view, params) {
function getPageData(context) {
@ -9,16 +9,20 @@ define(["loading", "listView", "cardBuilder", "libraryMenu", "libraryBrowser", "
if (!pageData) {
pageData = data[key] = {
query: {
SortBy: "SortName",
SortOrder: "Ascending",
IncludeItemTypes: "Playlist",
SortBy: 'SortName',
SortOrder: 'Ascending',
IncludeItemTypes: 'Playlist',
Recursive: true,
Fields: "PrimaryImageAspectRatio,SortName,CumulativeRunTimeTicks,CanDelete",
StartIndex: 0,
Limit: 100
Fields: 'PrimaryImageAspectRatio,SortName,CumulativeRunTimeTicks,CanDelete',
StartIndex: 0
},
view: libraryBrowser.getSavedView(key) || "Poster"
view: libraryBrowser.getSavedView(key) || 'Poster'
};
if (userSettings.libraryPageSize() > 0) {
pageData.query['Limit'] = userSettings.libraryPageSize();
}
pageData.query.ParentId = libraryMenu.getTopParentId();
libraryBrowser.loadSavedQueryValues(key, pageData.query);
}
@ -48,17 +52,17 @@ define(["loading", "listView", "cardBuilder", "libraryMenu", "libraryBrowser", "
function onViewStyleChange() {
var viewStyle = getPageData(view).view;
var itemsContainer = view.querySelector(".itemsContainer");
var itemsContainer = view.querySelector('.itemsContainer');
if ("List" == viewStyle) {
itemsContainer.classList.add("vertical-list");
itemsContainer.classList.remove("vertical-wrap");
if ('List' == viewStyle) {
itemsContainer.classList.add('vertical-list');
itemsContainer.classList.remove('vertical-wrap');
} else {
itemsContainer.classList.remove("vertical-list");
itemsContainer.classList.add("vertical-wrap");
itemsContainer.classList.remove('vertical-list');
itemsContainer.classList.add('vertical-wrap');
}
itemsContainer.innerHTML = "";
itemsContainer.innerHTML = '';
}
function reloadItems() {
@ -70,9 +74,9 @@ define(["loading", "listView", "cardBuilder", "libraryMenu", "libraryBrowser", "
var result = responses[0];
responses[1];
window.scrollTo(0, 0);
var html = "";
var html = '';
var viewStyle = getPageData(view).view;
view.querySelector(".listTopPaging").innerHTML = libraryBrowser.getQueryPagingHtml({
view.querySelector('.listTopPaging').innerHTML = libraryBrowser.getQueryPagingHtml({
startIndex: query.StartIndex,
limit: query.Limit,
totalRecordCount: result.TotalRecordCount,
@ -80,37 +84,37 @@ define(["loading", "listView", "cardBuilder", "libraryMenu", "libraryBrowser", "
showLimit: false,
updatePageSizeSetting: false,
addLayoutButton: true,
layouts: "List,Poster,PosterCard,Thumb,ThumbCard",
layouts: 'List,Poster,PosterCard,Thumb,ThumbCard',
currentLayout: viewStyle
});
if (result.TotalRecordCount) {
if (viewStyle == "List") {
if (viewStyle == 'List') {
html = listView.getListViewHtml({
items: result.Items,
sortBy: query.SortBy
});
} else if (viewStyle == "PosterCard") {
} else if (viewStyle == 'PosterCard') {
html = cardBuilder.getCardsHtml({
items: result.Items,
shape: "square",
shape: 'square',
coverImage: true,
showTitle: true,
cardLayout: true
});
} else if (viewStyle == "Thumb") {
} else if (viewStyle == 'Thumb') {
html = cardBuilder.getCardsHtml({
items: result.Items,
shape: "backdrop",
shape: 'backdrop',
showTitle: true,
centerText: true,
preferThumb: true,
overlayPlayButton: true
});
} else if (viewStyle == "ThumbCard") {
} else if (viewStyle == 'ThumbCard') {
html = cardBuilder.getCardsHtml({
items: result.Items,
shape: "backdrop",
shape: 'backdrop',
showTitle: true,
preferThumb: true,
cardLayout: true
@ -118,43 +122,47 @@ define(["loading", "listView", "cardBuilder", "libraryMenu", "libraryBrowser", "
} else {
html = cardBuilder.getCardsHtml({
items: result.Items,
shape: "square",
shape: 'square',
showTitle: true,
coverImage: true,
centerText: true,
overlayPlayButton: true
});
}
view.querySelector(".noItemsMessage").classList.add("hide");
view.querySelector('.noItemsMessage').classList.add('hide');
} else {
view.querySelector(".noItemsMessage").classList.remove("hide");
view.querySelector('.noItemsMessage').classList.remove('hide');
}
var elem = view.querySelector(".itemsContainer");
var elem = view.querySelector('.itemsContainer');
elem.innerHTML = html;
imageLoader.lazyChildren(elem);
var btnNextPage = view.querySelector(".btnNextPage");
var btnNextPage = view.querySelector('.btnNextPage');
if (btnNextPage) {
btnNextPage.addEventListener("click", function () {
query.StartIndex += query.Limit;
btnNextPage.addEventListener('click', function () {
if (userSettings.libraryPageSize() > 0) {
query.StartIndex += query.Limit;
}
reloadItems();
});
}
var btnPreviousPage = view.querySelector(".btnPreviousPage");
var btnPreviousPage = view.querySelector('.btnPreviousPage');
if (btnPreviousPage) {
btnPreviousPage.addEventListener("click", function () {
query.StartIndex -= query.Limit;
btnPreviousPage.addEventListener('click', function () {
if (userSettings.libraryPageSize() > 0) {
query.StartIndex = Math.max(0, query.StartIndex - query.Limit);
}
reloadItems();
});
}
var btnChangeLayout = view.querySelector(".btnChangeLayout");
var btnChangeLayout = view.querySelector('.btnChangeLayout');
if (btnChangeLayout) {
btnChangeLayout.addEventListener("layoutchange", function (e) {
btnChangeLayout.addEventListener('layoutchange', function (e) {
var layout = e.detail.viewStyle;
getPageData(view).view = layout;
libraryBrowser.saveViewSetting(getSavedQueryKey(view), layout);
@ -169,11 +177,11 @@ define(["loading", "listView", "cardBuilder", "libraryMenu", "libraryBrowser", "
}
var data = {};
view.addEventListener("viewbeforeshow", function () {
view.addEventListener('viewbeforeshow', function () {
reloadItems();
});
view.querySelector(".btnNewPlaylist").addEventListener("click", function () {
require(["playlistEditor"], function (playlistEditor) {
view.querySelector('.btnNewPlaylist').addEventListener('click', function () {
require(['playlistEditor'], function (playlistEditor) {
var serverId = ApiClient.serverInfo().Id;
new playlistEditor().show({
items: [],

View file

@ -1,451 +1,447 @@
define([
"jQuery",
"emby-button",
"emby-input",
"scripts/livetvcomponents",
"paper-icon-button-light",
"emby-itemscontainer",
"emby-collapse",
"emby-select",
"livetvcss",
"emby-checkbox",
"emby-slider",
"listViewStyle",
"dashboardcss",
"detailtablecss"], function () {
'jQuery',
'emby-button',
'emby-input',
'scripts/livetvcomponents',
'paper-icon-button-light',
'emby-itemscontainer',
'emby-collapse',
'emby-select',
'livetvcss',
'emby-checkbox',
'emby-slider',
'listViewStyle',
'dashboardcss',
'detailtablecss'], function () {
function defineRoute(newRoute) {
var path = newRoute.path;
console.debug("defining route: " + path);
newRoute.dictionary = "core";
console.debug('defining route: ' + path);
newRoute.dictionary = 'core';
Emby.Page.addRoute(path, newRoute);
}
console.debug("defining core routes");
console.debug('defining core routes');
defineRoute({
path: "/addplugin.html",
autoFocus: false,
roles: "admin",
controller: "dashboard/plugins/add"
});
defineRoute({
path: "/mypreferencesmenu.html",
autoFocus: false,
transition: "fade",
controller: "user/menu"
});
defineRoute({
path: "/myprofile.html",
autoFocus: false,
transition: "fade",
controller: "user/profile"
});
defineRoute({
path: "/addserver.html",
path: '/addserver.html',
autoFocus: false,
anonymous: true,
startup: true,
controller: "auth/addserver"
controller: 'auth/addserver'
});
defineRoute({
path: "/mypreferencesdisplay.html",
path: '/selectserver.html',
autoFocus: false,
transition: "fade",
controller: "user/display"
anonymous: true,
startup: true,
controller: 'auth/selectserver',
type: 'selectserver'
});
defineRoute({
path: "/mypreferenceshome.html",
autoFocus: false,
transition: "fade",
controller: "user/home"
path: '/forgotpassword.html',
anonymous: true,
startup: true,
controller: 'auth/forgotpassword'
});
defineRoute({
path: "/mypreferencesplayback.html",
path: '/forgotpasswordpin.html',
autoFocus: false,
transition: "fade",
controller: "user/playback"
});
defineRoute({
path: "/mypreferencessubtitles.html",
autoFocus: false,
transition: "fade",
controller: "user/subtitles"
});
defineRoute({
path: "/myPreferencesQuickConnect.html",
autoFocus: false,
transition: "fade",
controller: "user/quickConnect"
anonymous: true,
startup: true,
controller: 'auth/forgotpasswordpin'
});
defineRoute({
path: "/dashboard.html",
path: '/addplugin.html',
autoFocus: false,
roles: "admin",
controller: "dashboard/dashboard"
roles: 'admin',
controller: 'dashboard/plugins/add'
});
defineRoute({
path: "/dashboardgeneral.html",
controller: "dashboard/general",
path: '/mypreferencesmenu.html',
autoFocus: false,
roles: "admin"
transition: 'fade',
controller: 'user/menu'
});
defineRoute({
path: "/networking.html",
path: '/myprofile.html',
autoFocus: false,
roles: "admin",
controller: "dashboard/networking"
transition: 'fade',
controller: 'user/profile'
});
defineRoute({
path: "/devices.html",
path: '/mypreferencesdisplay.html',
autoFocus: false,
roles: "admin",
controller: "devices"
transition: 'fade',
controller: 'user/display'
});
defineRoute({
path: "/device.html",
path: '/myPreferencesQuickConnect.html',
autoFocus: false,
roles: "admin",
controller: "device"
transition: 'fade',
controller: 'user/quickConnect'
});
defineRoute({
path: '/mypreferenceshome.html',
autoFocus: false,
transition: 'fade',
controller: 'user/home'
});
defineRoute({
path: "/quickConnect.html",
path: '/mypreferencesplayback.html',
autoFocus: false,
roles: "admin",
transition: 'fade',
controller: 'user/playback'
});
defineRoute({
path: '/mypreferencessubtitles.html',
autoFocus: false,
transition: 'fade',
controller: 'user/subtitles'
});
defineRoute({
path: '/dashboard.html',
autoFocus: false,
roles: 'admin',
controller: 'dashboard/dashboard'
});
defineRoute({
path: '/dashboardgeneral.html',
controller: 'dashboard/general',
autoFocus: false,
roles: 'admin'
});
defineRoute({
path: '/networking.html',
autoFocus: false,
roles: 'admin',
controller: 'dashboard/networking'
});
defineRoute({
path: '/devices.html',
autoFocus: false,
roles: 'admin',
controller: 'dashboard/devices/devices'
});
defineRoute({
path: '/device.html',
autoFocus: false,
roles: 'admin',
controller: 'dashboard/devices/device'
});
defineRoute({
path: '/quickConnect.html',
autoFocus: false,
roles: 'admin',
controller: "quickConnect"
});
defineRoute({
path: "/dlnaprofile.html",
path: '/dlnaprofile.html',
autoFocus: false,
roles: "admin",
controller: "dlnaprofile"
roles: 'admin',
controller: 'dashboard/dlna/dlnaprofile'
});
defineRoute({
path: "/dlnaprofiles.html",
path: '/dlnaprofiles.html',
autoFocus: false,
roles: "admin",
controller: "dlnaprofiles"
roles: 'admin',
controller: 'dashboard/dlna/dlnaprofiles'
});
defineRoute({
path: "/dlnasettings.html",
path: '/dlnasettings.html',
autoFocus: false,
roles: "admin",
controller: "dlnasettings"
roles: 'admin',
controller: 'dashboard/dlna/dlnasettings'
});
defineRoute({
path: "/edititemmetadata.html",
controller: "edititemmetadata",
path: '/edititemmetadata.html',
controller: 'edititemmetadata',
autoFocus: false
});
defineRoute({
path: "/encodingsettings.html",
path: '/encodingsettings.html',
autoFocus: false,
roles: "admin",
controller: "encodingsettings"
roles: 'admin',
controller: 'dashboard/encodingsettings'
});
defineRoute({
path: "/forgotpassword.html",
anonymous: true,
startup: true,
controller: "auth/forgotpassword"
path: '/home.html',
autoFocus: false,
controller: 'home',
transition: 'fade',
type: 'home'
});
defineRoute({
path: "/forgotpasswordpin.html",
path: '/list.html',
autoFocus: false,
controller: 'list',
transition: 'fade'
});
defineRoute({
path: '/itemdetails.html',
controller: 'itemdetailpage',
autoFocus: false,
transition: 'fade'
});
defineRoute({
path: '/library.html',
autoFocus: false,
roles: 'admin',
controller: 'dashboard/medialibrarypage'
});
defineRoute({
path: '/librarydisplay.html',
autoFocus: false,
roles: 'admin',
controller: 'dashboard/librarydisplay'
});
defineRoute({
path: '/livetv.html',
controller: 'livetv/livetvsuggested',
autoFocus: false,
transition: 'fade'
});
defineRoute({
path: '/livetvguideprovider.html',
autoFocus: false,
roles: 'admin',
controller: 'livetvguideprovider'
});
defineRoute({
path: '/livetvsettings.html',
autoFocus: false,
controller: 'livetvsettings'
});
defineRoute({
path: '/livetvstatus.html',
autoFocus: false,
roles: 'admin',
controller: 'livetvstatus'
});
defineRoute({
path: '/livetvtuner.html',
autoFocus: false,
roles: 'admin',
controller: 'livetvtuner'
});
defineRoute({
path: '/log.html',
roles: 'admin',
controller: 'dashboard/logs'
});
defineRoute({
path: '/login.html',
autoFocus: false,
anonymous: true,
startup: true,
controller: "auth/forgotpasswordpin"
controller: 'auth/login',
type: 'login'
});
defineRoute({
path: "/home.html",
path: '/metadataimages.html',
autoFocus: false,
controller: "home",
transition: "fade",
type: "home"
roles: 'admin',
controller: 'dashboard/metadataimagespage'
});
defineRoute({
path: "/list.html",
path: '/metadatanfo.html',
autoFocus: false,
controller: "list",
transition: "fade"
roles: 'admin',
controller: 'dashboard/metadatanfo'
});
defineRoute({
path: "/index.html",
path: '/movies.html',
autoFocus: false,
isDefaultRoute: true
controller: 'movies/moviesrecommended',
transition: 'fade'
});
defineRoute({
path: "/itemdetails.html",
controller: "itemdetailpage",
path: '/music.html',
controller: 'music/musicrecommended',
autoFocus: false,
transition: "fade"
transition: 'fade'
});
defineRoute({
path: "/library.html",
path: '/notificationsetting.html',
autoFocus: false,
roles: "admin",
controller: "medialibrarypage"
roles: 'admin',
controller: 'dashboard/notifications/notification'
});
defineRoute({
path: "/librarydisplay.html",
path: '/notificationsettings.html',
controller: 'dashboard/notifications/notifications',
autoFocus: false,
roles: "admin",
controller: "librarydisplay"
roles: 'admin'
});
defineRoute({
path: "/librarysettings.html",
path: '/playbackconfiguration.html',
autoFocus: false,
roles: "admin",
controller: "librarysettings"
roles: 'admin',
controller: 'dashboard/playbackconfiguration'
});
defineRoute({
path: "/livetv.html",
controller: "livetv/livetvsuggested",
path: '/availableplugins.html',
autoFocus: false,
transition: "fade"
roles: 'admin',
controller: 'dashboard/plugins/available'
});
defineRoute({
path: "/livetvguideprovider.html",
path: '/installedplugins.html',
autoFocus: false,
roles: "admin",
controller: "livetvguideprovider"
roles: 'admin',
controller: 'dashboard/plugins/installed'
});
defineRoute({
path: "/livetvsettings.html",
path: '/scheduledtask.html',
autoFocus: false,
controller: "livetvsettings"
roles: 'admin',
controller: 'dashboard/scheduledtasks/scheduledtask'
});
defineRoute({
path: "/livetvstatus.html",
path: '/scheduledtasks.html',
autoFocus: false,
roles: "admin",
controller: "livetvstatus"
roles: 'admin',
controller: 'dashboard/scheduledtasks/scheduledtasks'
});
defineRoute({
path: "/livetvtuner.html",
path: '/search.html',
controller: 'searchpage'
});
defineRoute({
path: '/serveractivity.html',
autoFocus: false,
roles: "admin",
controller: "livetvtuner"
roles: 'admin',
controller: 'dashboard/serveractivity'
});
defineRoute({
path: "/log.html",
roles: "admin",
controller: "dashboard/logs"
});
defineRoute({
path: "/login.html",
path: '/apikeys.html',
autoFocus: false,
anonymous: true,
startup: true,
controller: "auth/login",
type: "login"
roles: 'admin',
controller: 'dashboard/apikeys'
});
defineRoute({
path: "/metadataimages.html",
path: '/streamingsettings.html',
autoFocus: false,
roles: "admin",
controller: "metadataimagespage"
roles: 'admin',
controller: 'dashboard/streamingsettings'
});
defineRoute({
path: "/metadatanfo.html",
path: '/tv.html',
autoFocus: false,
roles: "admin",
controller: "metadatanfo"
controller: 'shows/tvrecommended',
transition: 'fade'
});
defineRoute({
path: "/movies.html",
path: '/useredit.html',
autoFocus: false,
controller: "movies/moviesrecommended",
transition: "fade"
roles: 'admin',
controller: 'useredit'
});
defineRoute({
path: "/music.html",
controller: "music/musicrecommended",
path: '/userlibraryaccess.html',
autoFocus: false,
transition: "fade"
roles: 'admin',
controller: 'userlibraryaccess'
});
defineRoute({
path: "/notificationsetting.html",
path: '/usernew.html',
autoFocus: false,
roles: "admin",
controller: "dashboard/notifications/notification"
roles: 'admin',
controller: 'usernew'
});
defineRoute({
path: "/notificationsettings.html",
controller: "dashboard/notifications/notifications",
path: '/userparentalcontrol.html',
autoFocus: false,
roles: "admin"
roles: 'admin',
controller: 'userparentalcontrol'
});
defineRoute({
path: "/nowplaying.html",
controller: "playback/nowplaying",
path: '/userpassword.html',
autoFocus: false,
transition: "fade",
fullscreen: true,
supportsThemeMedia: true,
enableMediaControl: false
controller: 'userpasswordpage'
});
defineRoute({
path: "/playbackconfiguration.html",
path: '/userprofiles.html',
autoFocus: false,
roles: "admin",
controller: "playbackconfiguration"
});
defineRoute({
path: "/availableplugins.html",
autoFocus: false,
roles: "admin",
controller: "dashboard/plugins/available"
});
defineRoute({
path: "/installedplugins.html",
autoFocus: false,
roles: "admin",
controller: "dashboard/plugins/installed"
});
defineRoute({
path: "/scheduledtask.html",
autoFocus: false,
roles: "admin",
controller: "dashboard/scheduledtasks/scheduledtask"
});
defineRoute({
path: "/scheduledtasks.html",
autoFocus: false,
roles: "admin",
controller: "dashboard/scheduledtasks/scheduledtasks"
});
defineRoute({
path: "/search.html",
controller: "searchpage"
});
defineRoute({
path: "/selectserver.html",
autoFocus: false,
anonymous: true,
startup: true,
controller: "auth/selectserver",
type: "selectserver"
});
defineRoute({
path: "/serveractivity.html",
autoFocus: false,
roles: "admin",
controller: "serveractivity"
});
defineRoute({
path: "/apikeys.html",
autoFocus: false,
roles: "admin",
controller: "apikeys"
});
defineRoute({
path: "/streamingsettings.html",
autoFocus: false,
roles: "admin",
controller: "streamingsettings"
});
defineRoute({
path: "/tv.html",
autoFocus: false,
controller: "shows/tvrecommended",
transition: "fade"
});
defineRoute({
path: "/useredit.html",
autoFocus: false,
roles: "admin",
controller: "useredit"
});
defineRoute({
path: "/userlibraryaccess.html",
autoFocus: false,
roles: "admin",
controller: "userlibraryaccess"
});
defineRoute({
path: "/usernew.html",
autoFocus: false,
roles: "admin",
controller: "usernew"
});
defineRoute({
path: "/userparentalcontrol.html",
autoFocus: false,
roles: "admin",
controller: "userparentalcontrol"
});
defineRoute({
path: "/userpassword.html",
autoFocus: false,
controller: "userpasswordpage"
});
defineRoute({
path: "/userprofiles.html",
autoFocus: false,
roles: "admin",
controller: "userprofilespage"
roles: 'admin',
controller: 'userprofilespage'
});
defineRoute({
path: "/wizardremoteaccess.html",
path: '/wizardremoteaccess.html',
autoFocus: false,
anonymous: true,
controller: "wizard/remoteaccess"
controller: 'wizard/remoteaccess'
});
defineRoute({
path: "/wizardfinish.html",
path: '/wizardfinish.html',
autoFocus: false,
anonymous: true,
controller: "wizard/finish"
controller: 'wizard/finish'
});
defineRoute({
path: "/wizardlibrary.html",
path: '/wizardlibrary.html',
autoFocus: false,
anonymous: true,
controller: "medialibrarypage"
controller: 'medialibrarypage'
});
defineRoute({
path: "/wizardsettings.html",
path: '/wizardsettings.html',
autoFocus: false,
anonymous: true,
controller: "wizard/settings"
controller: 'wizard/settings'
});
defineRoute({
path: "/wizardstart.html",
path: '/wizardstart.html',
autoFocus: false,
anonymous: true,
controller: "wizard/start"
controller: 'wizard/start'
});
defineRoute({
path: "/wizarduser.html",
controller: "wizard/user",
path: '/wizarduser.html',
controller: 'wizard/user',
autoFocus: false,
anonymous: true
});
defineRoute({
path: "/videoosd.html",
transition: "fade",
controller: "playback/videoosd",
path: '/videoosd.html',
transition: 'fade',
controller: 'playback/videoosd',
autoFocus: false,
type: "video-osd",
type: 'video-osd',
supportsThemeMedia: true,
fullscreen: true,
enableMediaControl: false
});
defineRoute({
path: "/configurationpage",
path: '/nowplaying.html',
controller: 'playback/nowplaying',
autoFocus: false,
transition: 'fade',
fullscreen: true,
supportsThemeMedia: true,
enableMediaControl: false
});
defineRoute({
path: '/configurationpage',
autoFocus: false,
enableCache: false,
enableContentQueryString: true,
roles: "admin"
roles: 'admin'
});
defineRoute({
path: "/",
path: '/',
isDefaultRoute: true,
autoFocus: false
});
defineRoute({
path: '/index.html',
autoFocus: false,
isDefaultRoute: true
});
});

View file

@ -1,18 +1,18 @@
define(["searchFields", "searchResults", "events"], function (SearchFields, SearchResults, events) {
"use strict";
define(['searchFields', 'searchResults', 'events'], function (SearchFields, SearchResults, events) {
'use strict';
function init(instance, tabContent, options) {
tabContent.innerHTML = '<div class="padded-left padded-right searchFields"></div><div class="searchResults padded-top" style="padding-top:1.5em;"></div>';
instance.searchFields = new SearchFields({
element: tabContent.querySelector(".searchFields")
element: tabContent.querySelector('.searchFields')
});
instance.searchResults = new SearchResults({
element: tabContent.querySelector(".searchResults"),
element: tabContent.querySelector('.searchResults'),
serverId: ApiClient.serverId(),
parentId: options.parentId,
collectionType: options.collectionType
});
events.on(instance.searchFields, "search", function (e, value) {
events.on(instance.searchFields, 'search', function (e, value) {
instance.searchResults.search(value);
});
}

View file

@ -12,7 +12,7 @@ import events from 'events';
}
export function enableAutoLogin(val) {
if (val != null) {
if (val !== undefined) {
this.set('enableAutoLogin', val.toString());
}
@ -20,7 +20,7 @@ import events from 'events';
}
export function enableSystemExternalPlayers(val) {
if (val !== null) {
if (val !== undefined) {
this.set('enableSystemExternalPlayers', val.toString());
}
@ -29,7 +29,7 @@ import events from 'events';
export function enableAutomaticBitrateDetection(isInNetwork, mediaType, val) {
var key = 'enableautobitratebitrate-' + mediaType + '-' + isInNetwork;
if (val != null) {
if (val !== undefined) {
if (isInNetwork && mediaType === 'Audio') {
val = true;
}
@ -46,7 +46,7 @@ import events from 'events';
export function maxStreamingBitrate(isInNetwork, mediaType, val) {
var key = 'maxbitrate-' + mediaType + '-' + isInNetwork;
if (val != null) {
if (val !== undefined) {
if (isInNetwork && mediaType === 'Audio') {
// nothing to do, this is always a max value
} else {
@ -72,7 +72,7 @@ import events from 'events';
}
export function maxChromecastBitrate(val) {
if (val != null) {
if (val !== undefined) {
this.set('chromecastBitrate1', val);
}
@ -81,7 +81,7 @@ import events from 'events';
}
export function syncOnlyOnWifi(val) {
if (val != null) {
if (val !== undefined) {
this.set('syncOnlyOnWifi', val.toString());
}
@ -89,7 +89,7 @@ import events from 'events';
}
export function syncPath(val) {
if (val != null) {
if (val !== undefined) {
this.set('syncPath', val);
}
@ -97,7 +97,7 @@ import events from 'events';
}
export function cameraUploadServers(val) {
if (val != null) {
if (val !== undefined) {
this.set('cameraUploadServers', val.join(','));
}
@ -110,7 +110,7 @@ import events from 'events';
}
export function runAtStartup(val) {
if (val != null) {
if (val !== undefined) {
this.set('runatstartup', val.toString());
}

View file

@ -84,7 +84,7 @@ import events from 'events';
}
export function enableCinemaMode(val) {
if (val != null) {
if (val !== undefined) {
return this.set('enableCinemaMode', val.toString(), false);
}
@ -93,7 +93,7 @@ import events from 'events';
}
export function enableNextVideoInfoOverlay(val) {
if (val != null) {
if (val !== undefined) {
return this.set('enableNextVideoInfoOverlay', val.toString());
}
@ -102,7 +102,7 @@ import events from 'events';
}
export function enableThemeSongs(val) {
if (val != null) {
if (val !== undefined) {
return this.set('enableThemeSongs', val.toString(), false);
}
@ -111,7 +111,7 @@ import events from 'events';
}
export function enableThemeVideos(val) {
if (val != null) {
if (val !== undefined) {
return this.set('enableThemeVideos', val.toString(), false);
}
@ -120,7 +120,7 @@ import events from 'events';
}
export function enableFastFadein(val) {
if (val != null) {
if (val !== undefined) {
return this.set('fastFadein', val.toString(), false);
}
@ -129,7 +129,7 @@ import events from 'events';
}
export function enableBackdrops(val) {
if (val != null) {
if (val !== undefined) {
return this.set('enableBackdrops', val.toString(), false);
}
@ -138,7 +138,7 @@ import events from 'events';
}
export function language(val) {
if (val != null) {
if (val !== undefined) {
return this.set('language', val.toString(), false);
}
@ -146,7 +146,7 @@ import events from 'events';
}
export function dateTimeLocale(val) {
if (val != null) {
if (val !== undefined) {
return this.set('datetimelocale', val.toString(), false);
}
@ -154,7 +154,7 @@ import events from 'events';
}
export function skipBackLength(val) {
if (val != null) {
if (val !== undefined) {
return this.set('skipBackLength', val.toString());
}
@ -162,7 +162,7 @@ import events from 'events';
}
export function skipForwardLength(val) {
if (val != null) {
if (val !== undefined) {
return this.set('skipForwardLength', val.toString());
}
@ -170,7 +170,7 @@ import events from 'events';
}
export function dashboardTheme(val) {
if (val != null) {
if (val !== undefined) {
return this.set('dashboardTheme', val);
}
@ -178,7 +178,7 @@ import events from 'events';
}
export function skin(val) {
if (val != null) {
if (val !== undefined) {
return this.set('skin', val, false);
}
@ -186,7 +186,7 @@ import events from 'events';
}
export function theme(val) {
if (val != null) {
if (val !== undefined) {
return this.set('appTheme', val, false);
}
@ -194,15 +194,29 @@ import events from 'events';
}
export function screensaver(val) {
if (val != null) {
if (val !== undefined) {
return this.set('screensaver', val, false);
}
return this.get('screensaver', false);
}
export function libraryPageSize(val) {
if (val !== undefined) {
return this.set('libraryPageSize', parseInt(val, 10), false);
}
var libraryPageSize = parseInt(this.get('libraryPageSize', false), 10);
if (libraryPageSize === 0) {
// Explicitly return 0 to avoid returning 100 because 0 is falsy.
return 0;
} else {
return libraryPageSize || 100;
}
}
export function soundEffects(val) {
if (val != null) {
if (val !== undefined) {
return this.set('soundeffects', val, false);
}

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(function (response) {
return fetch('/config.json?nocache=' + new Date().getUTCMilliseconds()).then(function (response) {
data = response.json();
return data;
});
@ -11,5 +11,8 @@ function getConfig() {
export function enableMultiServer() {
return getConfig().then(config => {
return config.multiserver;
}).catch(error => {
console.log('cannot get web config:', error);
return false;
});
}

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
define(["events", "userSettings", "serverNotifications", "connectionManager", "emby-button"], function (events, userSettings, serverNotifications, connectionManager) {
"use strict";
define(['events', 'userSettings', 'serverNotifications', 'connectionManager', 'globalize', 'emby-button'], function (events, userSettings, serverNotifications, connectionManager, globalize) {
'use strict';
return function (options) {
function pollTasks() {
@ -26,12 +26,12 @@ define(["events", "userSettings", "serverNotifications", "connectionManager", "e
}
if (task.State == 'Idle') {
button.removeAttribute("disabled");
button.removeAttribute('disabled');
} else {
button.setAttribute("disabled", "disabled");
button.setAttribute('disabled', 'disabled');
}
button.setAttribute("data-taskid", task.Id);
button.setAttribute('data-taskid', task.Id);
var progress = (task.CurrentProgressPercentage || 0).toFixed(1);
if (options.progressElem) {
@ -47,12 +47,12 @@ define(["events", "userSettings", "serverNotifications", "connectionManager", "e
if (options.lastResultElem) {
var lastResult = task.LastExecutionResult ? task.LastExecutionResult.Status : '';
if (lastResult == "Failed") {
options.lastResultElem.html('<span style="color:#FF0000;">(' + Globalize.translate('LabelFailed') + ')</span>');
} else if (lastResult == "Cancelled") {
options.lastResultElem.html('<span style="color:#0026FF;">(' + Globalize.translate('LabelCancelled') + ')</span>');
} else if (lastResult == "Aborted") {
options.lastResultElem.html('<span style="color:#FF0000;">' + Globalize.translate('LabelAbortedByServerShutdown') + '</span>');
if (lastResult == 'Failed') {
options.lastResultElem.html('<span style="color:#FF0000;">(' + globalize.translate('LabelFailed') + ')</span>');
} else if (lastResult == 'Cancelled') {
options.lastResultElem.html('<span style="color:#0026FF;">(' + globalize.translate('LabelCancelled') + ')</span>');
} else if (lastResult == 'Aborted') {
options.lastResultElem.html('<span style="color:#FF0000;">' + globalize.translate('LabelAbortedByServerShutdown') + '</span>');
} else {
options.lastResultElem.html(lastResult);
}
@ -64,7 +64,7 @@ define(["events", "userSettings", "serverNotifications", "connectionManager", "e
}
function onButtonClick() {
onScheduledTaskMessageConfirmed(this.getAttribute("data-taskid"));
onScheduledTaskMessageConfirmed(this.getAttribute('data-taskid'));
}
function onScheduledTasksUpdate(e, apiClient, info) {
@ -89,12 +89,12 @@ define(["events", "userSettings", "serverNotifications", "connectionManager", "e
if (pollInterval) {
clearInterval(pollInterval);
}
apiClient.sendMessage("ScheduledTasksInfoStart", "1000,1000");
apiClient.sendMessage('ScheduledTasksInfoStart', '1000,1000');
pollInterval = setInterval(onPollIntervalFired, 5000);
}
function stopInterval() {
connectionManager.getApiClient(serverId).sendMessage("ScheduledTasksInfoStop");
connectionManager.getApiClient(serverId).sendMessage('ScheduledTasksInfoStop');
if (pollInterval) {
clearInterval(pollInterval);
@ -102,18 +102,18 @@ define(["events", "userSettings", "serverNotifications", "connectionManager", "e
}
if (options.panel) {
options.panel.classList.add("hide");
options.panel.classList.add('hide');
}
if (options.mode == 'off') {
button.removeEventListener("click", onButtonClick);
events.off(serverNotifications, "ScheduledTasksInfo", onScheduledTasksUpdate);
button.removeEventListener('click', onButtonClick);
events.off(serverNotifications, 'ScheduledTasksInfo', onScheduledTasksUpdate);
stopInterval();
} else {
button.addEventListener("click", onButtonClick);
button.addEventListener('click', onButtonClick);
pollTasks();
startInterval();
events.on(serverNotifications, "ScheduledTasksInfo", onScheduledTasksUpdate);
events.on(serverNotifications, 'ScheduledTasksInfo', onScheduledTasksUpdate);
}
};
});

View file

@ -1,19 +1,19 @@
define(["userSettings", "skinManager", "connectionManager", "events"], function (userSettings, skinManager, connectionManager, events) {
"use strict";
define(['userSettings', 'skinManager', 'connectionManager', 'events'], function (userSettings, skinManager, connectionManager, events) {
'use strict';
var currentViewType;
pageClassOn("viewbeforeshow", "page", function () {
pageClassOn('viewbeforeshow', 'page', function () {
var classList = this.classList;
var viewType = classList.contains("type-interior") || classList.contains("wizardPage") ? "a" : "b";
var viewType = classList.contains('type-interior') || classList.contains('wizardPage') ? 'a' : 'b';
if (viewType !== currentViewType) {
currentViewType = viewType;
var theme;
var context;
if ("a" === viewType) {
if ('a' === viewType) {
theme = userSettings.dashboardTheme();
context = "serverdashboard";
context = 'serverdashboard';
} else {
theme = userSettings.theme();
}
@ -21,7 +21,7 @@ define(["userSettings", "skinManager", "connectionManager", "events"], function
skinManager.setTheme(theme, context);
}
});
events.on(connectionManager, "localusersignedin", function (e, user) {
events.on(connectionManager, 'localusersignedin', function (e, user) {
currentViewType = null;
});
});