diff --git a/.github/stale.yml b/.github/stale.yml index e478e25d21..e61e0ed476 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -8,6 +8,7 @@ exemptLabels: - future - feature - enhancement + - confirmed # Label to use when marking an issue as stale staleLabel: stale # Comment to post when marking an issue as stale. Set to `false` to disable diff --git a/package.json b/package.json index 0a3cd85085..6ed08267d8 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "repository": "https://github.com/jellyfin/jellyfin-web", "license": "GPL-2.0-or-later", "devDependencies": { + "clean-webpack-plugin": "^3.0.0", "copy-webpack-plugin": "^5.0.3", "css-loader": "^2.1.0", "eslint": "^5.16.0", @@ -16,12 +17,14 @@ "webpack-merge": "^4.2.2" }, "dependencies": { + "alameda": "^1.3.0", "flv.js": "^1.5.0", "hls.js": "^0.12.4", "howler": "^2.1.2", "jquery": "^3.4.1", "jstree": "^3.3.7", "libjass": "^0.11.0", + "requirejs": "^2.3.5", "shaka-player": "^2.5.5", "sortablejs": "^1.9.0", "swiper": "^3.4.2", diff --git a/src/bower_components/alameda/alameda.js b/src/bower_components/alameda/alameda.js deleted file mode 100644 index 4ac0f7496b..0000000000 --- a/src/bower_components/alameda/alameda.js +++ /dev/null @@ -1,419 +0,0 @@ -var requirejs, require, define; -! function(global, Promise, undef) { - function commentReplace(match, singlePrefix) { - return singlePrefix || "" - } - - function hasProp(obj, prop) { - return hasOwn.call(obj, prop) - } - - function getOwn(obj, prop) { - return obj && hasProp(obj, prop) && obj[prop] - } - - function obj() { - return Object.create(null) - } - - function eachProp(obj, func) { - var prop; - for (prop in obj) - if (hasProp(obj, prop) && func(obj[prop], prop)) break - } - - function mixin(target, source, force, deepStringMixin) { - return source && eachProp(source, function(value, prop) { - !force && hasProp(target, prop) || (!deepStringMixin || "object" != typeof value || !value || Array.isArray(value) || "function" == typeof value || value instanceof RegExp ? target[prop] = value : (target[prop] || (target[prop] = {}), mixin(target[prop], value, force, deepStringMixin))) - }), target - } - - function getGlobal(value) { - if (!value) return value; - var g = global; - return value.split(".").forEach(function(part) { - g = g[part] - }), g - } - - function newContext(contextName) { - function trimDots(ary) { - var i, part, length = ary.length; - for (i = 0; i < length; i++) - if ("." === (part = ary[i])) ary.splice(i, 1), i -= 1; - else if (".." === part) { - if (0 === i || 1 === i && ".." === ary[2] || ".." === ary[i - 1]) continue; - i > 0 && (ary.splice(i - 1, 2), i -= 2) - } - } - - function normalize(name, baseName, applyMap) { - var mapValue, nameParts, i, j, nameSegment, lastIndex, foundMap, foundI, foundStarMap, starI, baseParts = baseName && baseName.split("/"), - normalizedBaseParts = baseParts, - map = config.map, - starMap = map && map["*"]; - if (name && (name = name.split("/"), lastIndex = name.length - 1, config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex]) && (name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, "")), "." === name[0].charAt(0) && baseParts && (normalizedBaseParts = baseParts.slice(0, baseParts.length - 1), name = normalizedBaseParts.concat(name)), trimDots(name), name = name.join("/")), applyMap && map && (baseParts || starMap)) { - nameParts = name.split("/"); - outerLoop: for (i = nameParts.length; i > 0; i -= 1) { - if (nameSegment = nameParts.slice(0, i).join("/"), baseParts) - for (j = baseParts.length; j > 0; j -= 1) - if ((mapValue = getOwn(map, baseParts.slice(0, j).join("/"))) && (mapValue = getOwn(mapValue, nameSegment))) { - foundMap = mapValue, foundI = i; - break outerLoop - }! foundStarMap && starMap && getOwn(starMap, nameSegment) && (foundStarMap = getOwn(starMap, nameSegment), starI = i) - }!foundMap && foundStarMap && (foundMap = foundStarMap, foundI = starI), foundMap && (nameParts.splice(0, foundI, foundMap), name = nameParts.join("/")) - } - return getOwn(config.pkgs, name) || name - } - - function makeShimExports(value) { - function fn() { - var ret; - return value.init && (ret = value.init.apply(global, arguments)), ret || value.exports && getGlobal(value.exports) - } - return fn - } - - function takeQueue(anonId) { - var i, id, args, shim; - for (i = 0; i < queue.length; i += 1) { - if ("string" != typeof queue[i][0]) { - if (!anonId) break; - queue[i].unshift(anonId), anonId = undef - } - args = queue.shift(), id = args[0], i -= 1, id in defined || id in waiting || (id in deferreds ? main.apply(undef, args) : waiting[id] = args) - } - anonId && (shim = getOwn(config.shim, anonId) || {}, main(anonId, shim.deps || [], shim.exportsFn)) - } - - function makeRequire(relName, topLevel) { - var req = function(deps, callback, errback, alt) { - var name, cfg; - if (topLevel && takeQueue(), "string" == typeof deps) { - if (handlers[deps]) return handlers[deps](relName); - if (!((name = makeMap(deps, relName, !0).id) in defined)) throw new Error("Not loaded: " + name); - return defined[name] - } - return deps && !Array.isArray(deps) && (cfg = deps, deps = undef, Array.isArray(callback) && (deps = callback, callback = errback, errback = alt), topLevel) ? req.config(cfg)(deps, callback, errback) : (callback = callback || function() { - return slice.call(arguments, 0) - }, asyncResolve.then(function() { - return takeQueue(), main(undef, deps || [], callback, errback, relName) - })) - }; - return req.isBrowser = "undefined" != typeof document && "undefined" != typeof navigator, req.nameToUrl = function(moduleName, ext, skipExt) { - var paths, syms, i, parentModule, url, parentPath, bundleId, pkgMain = getOwn(config.pkgs, moduleName); - if (pkgMain && (moduleName = pkgMain), bundleId = getOwn(bundlesMap, moduleName)) return req.nameToUrl(bundleId, ext, skipExt); - if (urlRegExp.test(moduleName)) url = moduleName + (ext || ""); - else { - for (paths = config.paths, syms = moduleName.split("/"), i = syms.length; i > 0; i -= 1) - if (parentModule = syms.slice(0, i).join("/"), parentPath = getOwn(paths, parentModule)) { - Array.isArray(parentPath) && (parentPath = parentPath[0]), syms.splice(0, i, parentPath); - break - } url = syms.join("/"), url += ext || (/^data\:|^blob\:|\?/.test(url) || skipExt ? "" : ".js"), url = ("/" === url.charAt(0) || url.match(/^[\w\+\.\-]+:/) ? "" : config.baseUrl) + url - } - return config.urlArgs && !/^blob\:/.test(url) ? url + config.urlArgs(moduleName, url) : url - }, req.toUrl = function(moduleNamePlusExt) { - var ext, index = moduleNamePlusExt.lastIndexOf("."), - segment = moduleNamePlusExt.split("/")[0], - isRelative = "." === segment || ".." === segment; - return -1 !== index && (!isRelative || index > 1) && (ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length), moduleNamePlusExt = moduleNamePlusExt.substring(0, index)), req.nameToUrl(normalize(moduleNamePlusExt, relName), ext, !0) - }, req.defined = function(id) { - return makeMap(id, relName, !0).id in defined - }, req.specified = function(id) { - return (id = makeMap(id, relName, !0).id) in defined || id in deferreds - }, req - } - - function resolve(name, d, value) { - name && (defined[name] = value, requirejs.onResourceLoad && requirejs.onResourceLoad(context, d.map, d.deps)), d.finished = !0, d.resolve(value) - } - - function reject(d, err) { - d.finished = !0, d.rejected = !0, d.reject(err) - } - - function makeNormalize(relName) { - return function(name) { - return normalize(name, relName, !0) - } - } - - function defineModule(d) { - d.factoryCalled = !0; - var ret, name = d.map.id; - try { - ret = context.execCb(name, d.factory, d.values, defined[name]) - } catch (err) { - return reject(d, err) - } - name ? ret === undef && (d.cjsModule ? ret = d.cjsModule.exports : d.usingExports && (ret = defined[name])) : requireDeferreds.splice(requireDeferreds.indexOf(d), 1), resolve(name, d, ret) - } - - function depFinished(val, i) { - this.rejected || this.depDefined[i] || (this.depDefined[i] = !0, this.depCount += 1, this.values[i] = val, this.depending || this.depCount !== this.depMax || defineModule(this)) - } - - function makeDefer(name, calculatedMap) { - var d = {}; - return d.promise = new Promise(function(resolve, reject) { - d.resolve = resolve, d.reject = function(err) { - name || requireDeferreds.splice(requireDeferreds.indexOf(d), 1), reject(err) - } - }), d.map = name ? calculatedMap || makeMap(name) : {}, d.depCount = 0, d.depMax = 0, d.values = [], d.depDefined = [], d.depFinished = depFinished, d.map.pr && (d.deps = [makeMap(d.map.pr)]), d - } - - function getDefer(name, calculatedMap) { - var d; - return name ? (d = name in deferreds && deferreds[name]) || (d = deferreds[name] = makeDefer(name, calculatedMap)) : (d = makeDefer(), requireDeferreds.push(d)), d - } - - function makeErrback(d, name) { - return function(err) { - d.rejected || (err.dynaId || (err.dynaId = "id" + (errCount += 1), err.requireModules = [name]), reject(d, err)) - } - } - - function waitForDep(depMap, relName, d, i) { - d.depMax += 1, callDep(depMap, relName).then(function(val) { - d.depFinished(val, i) - }, makeErrback(d, depMap.id)).catch(makeErrback(d, d.map.id)) - } - - function makeLoad(id) { - function load(value) { - fromTextCalled || resolve(id, getDefer(id), value) - } - var fromTextCalled; - return load.error = function(err) { - reject(getDefer(id), err) - }, load.fromText = function(text, textAlt) { - var execError, d = getDefer(id), - map = makeMap(makeMap(id).n), - plainId = map.id; - fromTextCalled = !0, d.factory = function(p, val) { - return val - }, textAlt && (text = textAlt), hasProp(config.config, id) && (config.config[plainId] = config.config[id]); - try { - req.exec(text) - } catch (e) { - execError = new Error("fromText eval for " + plainId + " failed: " + e), execError.requireType = "fromtexteval", reject(d, execError) - } - takeQueue(plainId), d.deps = [map], waitForDep(map, null, d, d.deps.length) - }, load - } - - function callPlugin(plugin, map, relName) { - plugin.load(map.n, makeRequire(relName), makeLoad(map.id), config) - } - - function splitPrefix(name) { - var prefix, index = name ? name.indexOf("!") : -1; - return index > -1 && (prefix = name.substring(0, index), name = name.substring(index + 1, name.length)), [prefix, name] - } - - function breakCycle(d, traced, processed) { - var id = d.map.id; - traced[id] = !0, !d.finished && d.deps && d.deps.forEach(function(depMap) { - var depId = depMap.id, - dep = !hasProp(handlers, depId) && getDefer(depId, depMap); - !dep || dep.finished || processed[depId] || (hasProp(traced, depId) ? d.deps.forEach(function(depMap, i) { - depMap.id === depId && d.depFinished(defined[depId], i) - }) : breakCycle(dep, traced, processed)) - }), processed[id] = !0 - } - - function check(d) { - var err, mid, dfd, notFinished = [], - waitInterval = 1e3 * config.waitSeconds, - expired = waitInterval && startTime + waitInterval < (new Date).getTime(); - if (0 === loadCount && (d ? d.finished || breakCycle(d, {}, {}) : requireDeferreds.length && requireDeferreds.forEach(function(d) { - breakCycle(d, {}, {}) - })), expired) { - for (mid in deferreds) dfd = deferreds[mid], dfd.finished || notFinished.push(dfd.map.id); - err = new Error("Timeout for modules: " + notFinished), err.requireModules = notFinished, err.requireType = "timeout", notFinished.forEach(function(id) { - reject(getDefer(id), err) - }) - } else(loadCount || requireDeferreds.length) && (checkingLater || (checkingLater = !0, setTimeout(function() { - checkingLater = !1, check() - }, 70))) - } - - function delayedError(e) { - console.log(e.stack); - return setTimeout(function() { - e.dynaId && trackedErrors[e.dynaId] || (trackedErrors[e.dynaId] = !0, req.onError(e)) - }), e - } - var req, main, makeMap, callDep, handlers, checkingLater, load, context, defined = obj(), - waiting = obj(), - config = { - waitSeconds: 7, - baseUrl: "./", - paths: {}, - bundles: {}, - pkgs: {}, - shim: {}, - config: {} - }, - mapCache = obj(), - requireDeferreds = [], - deferreds = obj(), - calledDefine = obj(), - calledPlugin = obj(), - loadCount = 0, - startTime = (new Date).getTime(), - errCount = 0, - trackedErrors = obj(), - urlFetched = obj(), - bundlesMap = obj(), - asyncResolve = Promise.resolve(undefined); - return load = "function" == typeof importScripts ? function(map) { - var url = map.url; - urlFetched[url] || (urlFetched[url] = !0, getDefer(map.id), importScripts(url), takeQueue(map.id)) - } : function(map) { - var script, id = map.id, - url = map.url; - urlFetched[url] || (urlFetched[url] = !0, script = document.createElement("script"), script.setAttribute("data-requiremodule", id), script.type = config.scriptType || "text/javascript", script.charset = "utf-8", script.async = !0, loadCount += 1, script.addEventListener("load", function() { - loadCount -= 1, takeQueue(id) - }, !1), script.addEventListener("error", function() { - loadCount -= 1; - var err, pathConfig = getOwn(config.paths, id); - if (pathConfig && Array.isArray(pathConfig) && pathConfig.length > 1) { - script.parentNode.removeChild(script), pathConfig.shift(); - var d = getDefer(id); - d.map = makeMap(id), d.map.url = req.nameToUrl(id), load(d.map) - } else err = new Error("Load failed: " + id + ": " + script.src), err.requireModules = [id], err.requireType = "scripterror", reject(getDefer(id), err) - }, !1), script.src = url, 10 === document.documentMode ? asap.then(function() { - document.head.appendChild(script) - }) : document.head.appendChild(script)) - }, callDep = function(map, relName) { - var args, bundleId, name = map.id, - shim = config.shim[name]; - if (name in waiting) args = waiting[name], delete waiting[name], main.apply(undef, args); - else if (!(name in deferreds)) - if (map.pr) { - if (!(bundleId = getOwn(bundlesMap, name))) return callDep(makeMap(map.pr)).then(function(plugin) { - var newMap = map.prn ? map : makeMap(name, relName, !0), - newId = newMap.id, - shim = getOwn(config.shim, newId); - return newId in calledPlugin || (calledPlugin[newId] = !0, shim && shim.deps ? req(shim.deps, function() { - callPlugin(plugin, newMap, relName) - }) : callPlugin(plugin, newMap, relName)), getDefer(newId).promise - }); - map.url = req.nameToUrl(bundleId), load(map) - } else shim && shim.deps ? req(shim.deps, function() { - load(map) - }) : load(map); - return getDefer(name).promise - }, makeMap = function(name, relName, applyMap) { - if ("string" != typeof name) return name; - var plugin, url, parts, prefix, result, prefixNormalized, cacheKey = name + " & " + (relName || "") + " & " + !!applyMap; - return parts = splitPrefix(name), prefix = parts[0], name = parts[1], !prefix && cacheKey in mapCache ? mapCache[cacheKey] : (prefix && (prefix = normalize(prefix, relName, applyMap), plugin = prefix in defined && defined[prefix]), prefix ? plugin && plugin.normalize ? (name = plugin.normalize(name, makeNormalize(relName)), prefixNormalized = !0) : name = -1 === name.indexOf("!") ? normalize(name, relName, applyMap) : name : (name = normalize(name, relName, applyMap), parts = splitPrefix(name), prefix = parts[0], name = parts[1], url = req.nameToUrl(name)), result = { - id: prefix ? prefix + "!" + name : name, - n: name, - pr: prefix, - url: url, - prn: prefix && prefixNormalized - }, prefix || (mapCache[cacheKey] = result), result) - }, handlers = { - require: function(name) { - return makeRequire(name) - }, - exports: function(name) { - var e = defined[name]; - return void 0 !== e ? e : defined[name] = {} - }, - module: function(name) { - return { - id: name, - uri: "", - exports: handlers.exports(name), - config: function() { - return getOwn(config.config, name) || {} - } - } - } - }, main = function(name, deps, factory, errback, relName) { - if (name) { - if (name in calledDefine) return; - calledDefine[name] = !0 - } - var d = getDefer(name); - return deps && !Array.isArray(deps) && (factory = deps, deps = []), deps = deps ? slice.call(deps, 0) : null, errback || (hasProp(config, "defaultErrback") ? config.defaultErrback && (errback = config.defaultErrback) : errback = delayedError), errback && d.promise.catch(errback), relName = relName || name, "function" == typeof factory ? (!deps.length && factory.length && (factory.toString().replace(commentRegExp, commentReplace).replace(cjsRequireRegExp, function(match, dep) { - deps.push(dep) - }), deps = (1 === factory.length ? ["require"] : ["require", "exports", "module"]).concat(deps)), d.factory = factory, d.deps = deps, d.depending = !0, deps.forEach(function(depName, i) { - var depMap; - deps[i] = depMap = makeMap(depName, relName, !0), depName = depMap.id, "require" === depName ? d.values[i] = handlers.require(name) : "exports" === depName ? (d.values[i] = handlers.exports(name), d.usingExports = !0) : "module" === depName ? d.values[i] = d.cjsModule = handlers.module(name) : void 0 === depName ? d.values[i] = void 0 : waitForDep(depMap, relName, d, i) - }), d.depending = !1, d.depCount === d.depMax && defineModule(d)) : name && resolve(name, d, factory), startTime = (new Date).getTime(), name || check(d), d.promise - }, req = makeRequire(null, !0), req.config = function(cfg) { - if (cfg.context && cfg.context !== contextName) { - var existingContext = getOwn(contexts, cfg.context); - return existingContext ? existingContext.req.config(cfg) : newContext(cfg.context).config(cfg) - } - if (mapCache = obj(), cfg.baseUrl && "/" !== cfg.baseUrl.charAt(cfg.baseUrl.length - 1) && (cfg.baseUrl += "/"), "string" == typeof cfg.urlArgs) { - var urlArgs = cfg.urlArgs; - cfg.urlArgs = function(id, url) { - return (-1 === url.indexOf("?") ? "?" : "&") + urlArgs - } - } - var shim = config.shim, - objs = { - paths: !0, - bundles: !0, - config: !0, - map: !0 - }; - return eachProp(cfg, function(value, prop) { - objs[prop] ? (config[prop] || (config[prop] = {}), mixin(config[prop], value, !0, !0)) : config[prop] = value - }), cfg.bundles && eachProp(cfg.bundles, function(value, prop) { - value.forEach(function(v) { - v !== prop && (bundlesMap[v] = prop) - }) - }), cfg.shim && (eachProp(cfg.shim, function(value, id) { - Array.isArray(value) && (value = { - deps: value - }), !value.exports && !value.init || value.exportsFn || (value.exportsFn = makeShimExports(value)), shim[id] = value - }), config.shim = shim), cfg.packages && cfg.packages.forEach(function(pkgObj) { - var location, name; - pkgObj = "string" == typeof pkgObj ? { - name: pkgObj - } : pkgObj, name = pkgObj.name, location = pkgObj.location, location && (config.paths[name] = pkgObj.location), config.pkgs[name] = pkgObj.name + "/" + (pkgObj.main || "main").replace(currDirRegExp, "").replace(jsSuffixRegExp, "") - }), (cfg.deps || cfg.callback) && req(cfg.deps, cfg.callback), req - }, req.onError = function(err) { - throw err - }, context = { - id: contextName, - defined: defined, - waiting: waiting, - config: config, - deferreds: deferreds, - req: req, - execCb: function(name, callback, args, exports) { - return callback.apply(exports, args) - } - }, contexts[contextName] = context, req - } - if (!Promise) throw new Error("No Promise implementation available"); - var topReq, dataMain, src, subPath, bootstrapConfig = requirejs || require, - hasOwn = Object.prototype.hasOwnProperty, - contexts = {}, - queue = [], - currDirRegExp = /^\.\//, - urlRegExp = /^\/|\:|\?|\.js$/, - commentRegExp = /\/\*[\s\S]*?\*\/|([^:"'=]|^)\/\/.*$/gm, - cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g, - jsSuffixRegExp = /\.js$/, - slice = Array.prototype.slice; - if ("function" != typeof requirejs) { - var asap = Promise.resolve(void 0); - requirejs = topReq = newContext("_"), "function" != typeof require && (require = topReq), topReq.exec = function(text) { - return eval(text) - }, topReq.contexts = contexts, define = function() { - queue.push(slice.call(arguments, 0)) - }, define.amd = { - jQuery: !0 - }, bootstrapConfig && topReq.config(bootstrapConfig), topReq.isBrowser && !contexts._.config.skipDataMain && (dataMain = document.querySelectorAll("script[data-main]")[0], (dataMain = dataMain && dataMain.getAttribute("data-main")) && (dataMain = dataMain.replace(jsSuffixRegExp, ""), bootstrapConfig && bootstrapConfig.baseUrl || -1 !== dataMain.indexOf("!") || (src = dataMain.split("/"), dataMain = src.pop(), subPath = src.length ? src.join("/") + "/" : "./", topReq.config({ - baseUrl: subPath - })), topReq([dataMain]))) - } -}(this, "undefined" != typeof Promise ? Promise : void 0); diff --git a/src/bower_components/apiclient/connectionmanager.js b/src/bower_components/apiclient/connectionmanager.js index 8724300658..dcb8f28bc8 100644 --- a/src/bower_components/apiclient/connectionmanager.js +++ b/src/bower_components/apiclient/connectionmanager.js @@ -1,747 +1,804 @@ -define(["events", "apiclient", "appStorage"], function(events, apiClientFactory, appStorage) { +define(["events", "apiclient", "appStorage"], function (events, apiClientFactory, appStorage) { "use strict"; function getServerAddress(server, mode) { switch (mode) { case ConnectionMode.Local: return server.LocalAddress; + case ConnectionMode.Manual: return server.ManualAddress; + case ConnectionMode.Remote: return server.RemoteAddress; + default: - return server.ManualAddress || server.LocalAddress || server.RemoteAddress + return server.ManualAddress || server.LocalAddress || server.RemoteAddress; } } function paramsToString(params) { var values = []; + for (var key in params) { var value = params[key]; - null !== value && void 0 !== value && "" !== value && values.push(encodeURIComponent(key) + "=" + encodeURIComponent(value)) + + if (null !== value && void 0 !== value && "" !== value) { + values.push(encodeURIComponent(key) + "=" + encodeURIComponent(value)); + } } - return values.join("&") + + return values.join("&"); } function resolveFailure(instance, resolve) { resolve({ State: "Unavailable", - ConnectUser: instance.connectUser() - }) + }); } function mergeServers(credentialProvider, list1, list2) { - for (var i = 0, length = list2.length; i < length; i++) credentialProvider.addOrUpdateServer(list1, list2[i]); - return list1 + for (var i = 0, length = list2.length; i < length; i++) { + credentialProvider.addOrUpdateServer(list1, list2[i]); + } + + return list1; } function updateServerInfo(server, systemInfo) { - server.Name = systemInfo.ServerName, systemInfo.Id && (server.Id = systemInfo.Id), systemInfo.LocalAddress && (server.LocalAddress = systemInfo.LocalAddress) + server.Name = systemInfo.ServerName; + if (systemInfo.Id) { + server.Id = systemInfo.Id; + } + + if (systemInfo.LocalAddress) { + server.LocalAddress = systemInfo.LocalAddress; + } } function getEmbyServerUrl(baseUrl, handler) { - return baseUrl + "/" + handler + return baseUrl + "/" + handler; } function getFetchPromise(request) { var headers = request.headers || {}; - "json" === request.dataType && (headers.accept = "application/json"); + + if ("json" === request.dataType) { + headers.accept = "application/json"; + } + var fetchRequest = { - headers: headers, - method: request.type, - credentials: "same-origin" - }, - contentType = request.contentType; - return request.data && ("string" == typeof request.data ? fetchRequest.body = request.data : (fetchRequest.body = paramsToString(request.data), contentType = contentType || "application/x-www-form-urlencoded; charset=UTF-8")), contentType && (headers["Content-Type"] = contentType), request.timeout ? fetchWithTimeout(request.url, fetchRequest, request.timeout) : fetch(request.url, fetchRequest) + headers: headers, + method: request.type, + credentials: "same-origin" + }; + var contentType = request.contentType; + + if (request.data) { + if ("string" == typeof request.data) { + fetchRequest.body = request.data; + } else { + fetchRequest.body = paramsToString(request.data); + contentType = contentType || "application/x-www-form-urlencoded; charset=UTF-8"; + } + } + + if (contentType) { + headers["Content-Type"] = contentType; + } + + if (request.timeout) { + return fetchWithTimeout(request.url, fetchRequest, request.timeout); + } + + return fetch(request.url, fetchRequest); } function fetchWithTimeout(url, options, timeoutMs) { - return console.log("fetchWithTimeout: timeoutMs: " + timeoutMs + ", url: " + url), new Promise(function(resolve, reject) { + console.log("fetchWithTimeout: timeoutMs: " + timeoutMs + ", url: " + url); + return new Promise(function (resolve, reject) { var timeout = setTimeout(reject, timeoutMs); - options = options || {}, options.credentials = "same-origin", fetch(url, options).then(function(response) { - clearTimeout(timeout), console.log("fetchWithTimeout: succeeded connecting to url: " + url), resolve(response) - }, function(error) { - clearTimeout(timeout), console.log("fetchWithTimeout: timed out connecting to url: " + url), reject() - }) - }) + options = options || {}; + options.credentials = "same-origin"; + fetch(url, options).then(function (response) { + clearTimeout(timeout); + console.log("fetchWithTimeout: succeeded connecting to url: " + url); + resolve(response); + }, function (error) { + clearTimeout(timeout); + console.log("fetchWithTimeout: timed out connecting to url: " + url); + reject(); + }); + }); } function ajax(request) { - if (!request) throw new Error("Request cannot be null"); - return request.headers = request.headers || {}, console.log("ConnectionManager requesting url: " + request.url), getFetchPromise(request).then(function(response) { - return console.log("ConnectionManager response status: " + response.status + ", url: " + request.url), response.status < 400 ? "json" === request.dataType || "application/json" === request.headers.accept ? response.json() : response : Promise.reject(response) - }, function(err) { - throw console.log("ConnectionManager request failed to url: " + request.url), err - }) - } + if (!request) { + throw new Error("Request cannot be null"); + } - function getConnectUrl(handler) { - return "https://connect.emby.media/service/" + handler + request.headers = request.headers || {}; + console.log("ConnectionManager requesting url: " + request.url); + return getFetchPromise(request).then(function (response) { + console.log("ConnectionManager response status: " + response.status + ", url: " + request.url); + + if (response.status < 400) { + if ("json" === request.dataType || "application/json" === request.headers.accept) { + return response.json(); + } + + return response; + } + + return Promise.reject(response); + }, function (err) { + console.log("ConnectionManager request failed to url: " + request.url); + throw err; + }); } function replaceAll(originalString, strReplace, strWith) { var reg = new RegExp(strReplace, "ig"); - return originalString.replace(reg, strWith) + return originalString.replace(reg, strWith); } function normalizeAddress(address) { - return address = address.trim(), 0 !== address.toLowerCase().indexOf("http") && (address = "http://" + address), address = replaceAll(address, "Http:", "http:"), address = replaceAll(address, "Https:", "https:") + address = address.trim(); + + if (0 !== address.toLowerCase().indexOf("http")) { + address = "http://" + address; + } + + address = replaceAll(address, "Http:", "http:"); + address = replaceAll(address, "Https:", "https:"); + + return address; } function stringEqualsIgnoreCase(str1, str2) { - return (str1 || "").toLowerCase() === (str2 || "").toLowerCase() + return (str1 || "").toLowerCase() === (str2 || "").toLowerCase(); } function compareVersions(a, b) { - a = a.split("."), b = b.split("."); + a = a.split("."); + b = b.split("."); + for (var i = 0, length = Math.max(a.length, b.length); i < length; i++) { - var aVal = parseInt(a[i] || "0"), - bVal = parseInt(b[i] || "0"); - if (aVal < bVal) return -1; - if (aVal > bVal) return 1 + var aVal = parseInt(a[i] || "0"); + var bVal = parseInt(b[i] || "0"); + + if (aVal < bVal) { + return -1; + } + + if (aVal > bVal) { + return 1; + } } - return 0 + + return 0; } - var defaultTimeout = 2e4, - ConnectionMode = { - Local: 0, - Remote: 1, - Manual: 2 - }, - ConnectionManager = function(credentialProvider, appName, appVersion, deviceName, deviceId, capabilities, devicePixelRatio) { - function onConnectUserSignIn(user) { - connectUser = user, events.trigger(self, "connectusersignedin", [user]) + + var defaultTimeout = 20000; + var ConnectionMode = { + Local: 0, + Remote: 1, + Manual: 2 + }; + + var ConnectionManager = function (credentialProvider, appName, appVersion, deviceName, deviceId, capabilities, devicePixelRatio) { + + function onAuthenticated(apiClient, result, options, saveCredentials) { + var credentials = credentialProvider.credentials(); + var servers = credentials.Servers.filter(function (s) { + return s.Id === result.ServerId; + }); + var server = servers.length ? servers[0] : apiClient.serverInfo(); + + if (false !== options.updateDateLastAccessed) { + server.DateLastAccessed = new Date().getTime(); } - function onAuthenticated(apiClient, result, options, saveCredentials) { - var credentials = credentialProvider.credentials(), - servers = credentials.Servers.filter(function(s) { - return s.Id === result.ServerId - }), - server = servers.length ? servers[0] : apiClient.serverInfo(); - return !1 !== options.updateDateLastAccessed && (server.DateLastAccessed = (new Date).getTime()), server.Id = result.ServerId, saveCredentials ? (server.UserId = result.User.Id, server.AccessToken = result.AccessToken) : (server.UserId = null, server.AccessToken = null), credentialProvider.addOrUpdateServer(credentials.Servers, server), credentialProvider.credentials(credentials), apiClient.enableAutomaticBitrateDetection = options.enableAutomaticBitrateDetection, apiClient.serverInfo(server), afterConnected(apiClient, options), onLocalUserSignIn(server, apiClient.serverAddress(), result.User) + server.Id = result.ServerId; + + if (saveCredentials) { + server.UserId = result.User.Id; + server.AccessToken = result.AccessToken; + } else { + server.UserId = null; + server.AccessToken = null; } - function afterConnected(apiClient, options) { - options = options || {}, !1 !== options.reportCapabilities && apiClient.reportCapabilities(capabilities), apiClient.enableAutomaticBitrateDetection = options.enableAutomaticBitrateDetection, !1 !== options.enableWebSocket && (console.log("calling apiClient.ensureWebSocket"), apiClient.ensureWebSocket()) + credentialProvider.addOrUpdateServer(credentials.Servers, server); + credentialProvider.credentials(credentials); + apiClient.enableAutomaticBitrateDetection = options.enableAutomaticBitrateDetection; + apiClient.serverInfo(server); + afterConnected(apiClient, options); + return onLocalUserSignIn(server, apiClient.serverAddress(), result.User); + } + + function afterConnected(apiClient, options) { + options = options || {}; + + if (false !== options.reportCapabilities) { + apiClient.reportCapabilities(capabilities); } - function onLocalUserSignIn(server, serverUrl, user) { - return self._getOrAddApiClient(server, serverUrl), (self.onLocalUserSignedIn ? self.onLocalUserSignedIn.call(self, user) : Promise.resolve()).then(function() { - events.trigger(self, "localusersignedin", [user]) - }) - } + apiClient.enableAutomaticBitrateDetection = options.enableAutomaticBitrateDetection; - function ensureConnectUser(credentials) { - return connectUser && connectUser.Id === credentials.ConnectUserId ? Promise.resolve() : credentials.ConnectUserId && credentials.ConnectAccessToken ? (connectUser = null, getConnectUser(credentials.ConnectUserId, credentials.ConnectAccessToken).then(function(user) { - return onConnectUserSignIn(user), Promise.resolve() - }, function() { - return Promise.resolve() - })) : Promise.resolve() + if (false !== options.enableWebSocket) { + console.log("calling apiClient.ensureWebSocket"); + apiClient.ensureWebSocket(); } + } - function getConnectUser(userId, accessToken) { - if (!userId) throw new Error("null userId"); - if (!accessToken) throw new Error("null accessToken"); - return ajax({ - type: "GET", - url: "https://connect.emby.media/service/user?id=" + userId, - dataType: "json", - headers: { - "X-Application": appName + "/" + appVersion, - "X-Connect-UserToken": accessToken - } - }) - } + function onLocalUserSignIn(server, serverUrl, user) { + self._getOrAddApiClient(server, serverUrl); - function addAuthenticationInfoFromConnect(server, serverUrl, credentials) { - if (!server.ExchangeToken) throw new Error("server.ExchangeToken cannot be null"); - if (!credentials.ConnectUserId) throw new Error("credentials.ConnectUserId cannot be null"); - var url = getEmbyServerUrl(serverUrl, "Connect/Exchange?format=json&ConnectUserId=" + credentials.ConnectUserId), - auth = 'MediaBrowser Client="' + appName + '", Device="' + deviceName + '", DeviceId="' + deviceId + '", Version="' + appVersion + '"'; - return ajax({ - type: "GET", - url: url, - dataType: "json", - headers: { - "X-MediaBrowser-Token": server.ExchangeToken, - "X-Emby-Authorization": auth - } - }).then(function(auth) { - return server.UserId = auth.LocalUserId, server.AccessToken = auth.AccessToken, auth - }, function() { - return server.UserId = null, server.AccessToken = null, Promise.reject() - }) - } + var promise = self.onLocalUserSignedIn ? self.onLocalUserSignedIn.call(self, user) : Promise.resolve(); + return promise.then(function () { + events.trigger(self, "localusersignedin", [user]) + }) + } - function validateAuthentication(server, serverUrl) { - return ajax({ - type: "GET", - url: getEmbyServerUrl(serverUrl, "System/Info"), - dataType: "json", - headers: { - "X-MediaBrowser-Token": server.AccessToken - } - }).then(function(systemInfo) { - return updateServerInfo(server, systemInfo), Promise.resolve() - }, function() { - return server.UserId = null, server.AccessToken = null, Promise.resolve() - }) - } - - function getImageUrl(localUser) { - if (connectUser && connectUser.ImageUrl) return { - url: connectUser.ImageUrl - }; - if (localUser && localUser.PrimaryImageTag) { - return { - url: self.getApiClient(localUser).getUserImageUrl(localUser.Id, { - tag: localUser.PrimaryImageTag, - type: "Primary" - }), - supportsParams: !0 - } + function validateAuthentication(server, serverUrl) { + return ajax({ + type: "GET", + url: getEmbyServerUrl(serverUrl, "System/Info"), + dataType: "json", + headers: { + "X-MediaBrowser-Token": server.AccessToken } + }).then(function (systemInfo) { + updateServerInfo(server, systemInfo); + return Promise.resolve(); + }, function () { + server.UserId = null; + server.AccessToken = null; + return Promise.resolve(); + }); + } + + function getImageUrl(localUser) { + if (localUser && localUser.PrimaryImageTag) { return { - url: null, - supportsParams: !1 + url: self.getApiClient(localUser).getUserImageUrl(localUser.Id, { + tag: localUser.PrimaryImageTag, + type: "Primary" + }), + supportsParams: true + }; + } + + return { + url: null, + supportsParams: false + }; + } + + function logoutOfServer(apiClient) { + var serverInfo = apiClient.serverInfo() || {}; + var logoutInfo = { + serverId: serverInfo.Id + }; + return apiClient.logout().then(function () { + events.trigger(self, "localusersignedout", [logoutInfo]); + }, function () { + events.trigger(self, "localusersignedout", [logoutInfo]); + }); + } + + function findServers() { + return new Promise(function (resolve, reject) { + var onFinish = function (foundServers) { + var servers = foundServers.map(function (foundServer) { + var info = { + Id: foundServer.Id, + LocalAddress: convertEndpointAddressToManualAddress(foundServer) || foundServer.Address, + Name: foundServer.Name + }; + info.LastConnectionMode = info.ManualAddress ? ConnectionMode.Manual : ConnectionMode.Local; + return info; + }); + resolve(servers); + }; + + if (window.NativeShell && typeof window.NativeShell.findServers === 'function') { + window.NativeShell.findServers(1e3).then(onFinish, function () { + onFinish([]); + }); + } else { + resolve([]); } - } + }); + } - function logoutOfServer(apiClient) { - var serverInfo = apiClient.serverInfo() || {}, - logoutInfo = { - serverId: serverInfo.Id - }; - return apiClient.logout().then(function() { - events.trigger(self, "localusersignedout", [logoutInfo]) - }, function() { - events.trigger(self, "localusersignedout", [logoutInfo]) - }) - } + function convertEndpointAddressToManualAddress(info) { + if (info.Address && info.EndpointAddress) { + var address = info.EndpointAddress.split(":")[0]; + var parts = info.Address.split(":"); - function getConnectServers(credentials) { - return console.log("Begin getConnectServers"), credentials.ConnectAccessToken && credentials.ConnectUserId ? ajax({ - type: "GET", - url: "https://connect.emby.media/service/servers?userId=" + credentials.ConnectUserId, - dataType: "json", - headers: { - "X-Application": appName + "/" + appVersion, - "X-Connect-UserToken": credentials.ConnectAccessToken + if (parts.length > 1) { + var portString = parts[parts.length - 1]; + + if (!isNaN(parseInt(portString))) { + address += ":" + portString; } - }).then(function(servers) { - return servers.map(function(i) { - return { - ExchangeToken: i.AccessKey, - ConnectServerId: i.Id, - Id: i.SystemId, - Name: i.Name, - RemoteAddress: i.Url, - LocalAddress: i.LocalAddress, - UserLinkType: "guest" === (i.UserType || "").toLowerCase() ? "Guest" : "LinkedUser" - } - }) - }, function() { - return credentials.Servers.slice(0).filter(function(s) { - return s.ExchangeToken - }) - }) : Promise.resolve([]) - } - - function filterServers(servers, connectServers) { - return servers.filter(function(server) { - return !server.ExchangeToken || connectServers.filter(function(connectServer) { - return server.Id === connectServer.Id - }).length > 0 - }) - } - - function findServers() { - return new Promise(function(resolve, reject) { - var onFinish = function(foundServers) { - var servers = foundServers.map(function(foundServer) { - var info = { - Id: foundServer.Id, - LocalAddress: convertEndpointAddressToManualAddress(foundServer) || foundServer.Address, - Name: foundServer.Name - }; - return info.LastConnectionMode = info.ManualAddress ? ConnectionMode.Manual : ConnectionMode.Local, info - }); - resolve(servers) - }; - - if (window.NativeShell && typeof window.NativeShell.findServers === 'function') { - window.NativeShell.findServers(1e3).then(onFinish, function() { - onFinish([]) - }); - } else { - resolve([]); - } - }); - } - - function convertEndpointAddressToManualAddress(info) { - if (info.Address && info.EndpointAddress) { - var address = info.EndpointAddress.split(":")[0], - parts = info.Address.split(":"); - if (parts.length > 1) { - var portString = parts[parts.length - 1]; - isNaN(parseInt(portString)) || (address += ":" + portString) - } - return normalizeAddress(address) } - return null + + return normalizeAddress(address); } - function getTryConnectPromise(url, connectionMode, state, resolve, reject) { - console.log("getTryConnectPromise " + url), ajax({ - url: getEmbyServerUrl(url, "system/info/public"), - timeout: defaultTimeout, - type: "GET", - dataType: "json" - }).then(function(result) { - state.resolved || (state.resolved = !0, console.log("Reconnect succeeded to " + url), resolve({ + return null; + } + + function getTryConnectPromise(url, connectionMode, state, resolve, reject) { + console.log("getTryConnectPromise " + url); + ajax({ + url: getEmbyServerUrl(url, "system/info/public"), + timeout: defaultTimeout, + type: "GET", + dataType: "json" + }).then(function (result) { + if (!state.resolved) { + state.resolved = true; + console.log("Reconnect succeeded to " + url); + resolve({ url: url, connectionMode: connectionMode, data: result - })) - }, function() { - state.resolved || (console.log("Reconnect failed to " + url), ++state.rejects >= state.numAddresses && reject()) - }) - } + }); + } + }, function () { + if (!state.resolved) { + console.log("Reconnect failed to " + url); - function tryReconnect(serverInfo) { - var addresses = [], - addressesStrings = []; - return !serverInfo.manualAddressOnly && serverInfo.LocalAddress && -1 === addressesStrings.indexOf(serverInfo.LocalAddress) && (addresses.push({ + if (++state.rejects >= state.numAddresses) { + reject(); + } + } + }); + } + + function tryReconnect(serverInfo) { + var addresses = []; + var addressesStrings = []; + + if (!serverInfo.manualAddressOnly && serverInfo.LocalAddress && -1 === addressesStrings.indexOf(serverInfo.LocalAddress)) { + addresses.push({ url: serverInfo.LocalAddress, mode: ConnectionMode.Local, timeout: 0 - }), addressesStrings.push(addresses[addresses.length - 1].url)), serverInfo.ManualAddress && -1 === addressesStrings.indexOf(serverInfo.ManualAddress) && (addresses.push({ + }); + addressesStrings.push(addresses[addresses.length - 1].url); + } + + if (serverInfo.ManualAddress && -1 === addressesStrings.indexOf(serverInfo.ManualAddress)) { + addresses.push({ url: serverInfo.ManualAddress, mode: ConnectionMode.Manual, timeout: 100 - }), addressesStrings.push(addresses[addresses.length - 1].url)), !serverInfo.manualAddressOnly && serverInfo.RemoteAddress && -1 === addressesStrings.indexOf(serverInfo.RemoteAddress) && (addresses.push({ + }); + addressesStrings.push(addresses[addresses.length - 1].url); + } + + if (!serverInfo.manualAddressOnly && serverInfo.RemoteAddress && -1 === addressesStrings.indexOf(serverInfo.RemoteAddress)) { + addresses.push({ url: serverInfo.RemoteAddress, mode: ConnectionMode.Remote, timeout: 200 - }), addressesStrings.push(addresses[addresses.length - 1].url)), console.log("tryReconnect: " + addressesStrings.join("|")), new Promise(function(resolve, reject) { - var state = {}; - state.numAddresses = addresses.length, state.rejects = 0, addresses.map(function(url) { - setTimeout(function() { - state.resolved || getTryConnectPromise(url.url, url.mode, state, resolve, reject) - }, url.timeout) - }) - }) + }); + addressesStrings.push(addresses[addresses.length - 1].url); } - function onSuccessfulConnection(server, systemInfo, connectionMode, serverUrl, options, resolve) { - var credentials = credentialProvider.credentials(); - options = options || {}, credentials.ConnectAccessToken && !1 !== options.enableAutoLogin ? ensureConnectUser(credentials).then(function() { - server.ExchangeToken ? addAuthenticationInfoFromConnect(server, serverUrl, credentials).then(function() { - afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, !0, options, resolve) - }, function() { - afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, !0, options, resolve) - }) : afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, !0, options, resolve) - }) : afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, !0, options, resolve) - } - - function afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, verifyLocalAuthentication, options, resolve) { - if (options = options || {}, !1 === options.enableAutoLogin) server.UserId = null, server.AccessToken = null; - else if (verifyLocalAuthentication && server.AccessToken && !1 !== options.enableAutoLogin) return void validateAuthentication(server, serverUrl).then(function() { - afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, !1, options, resolve) - }); - updateServerInfo(server, systemInfo), server.LastConnectionMode = connectionMode, !1 !== options.updateDateLastAccessed && (server.DateLastAccessed = (new Date).getTime()), credentialProvider.addOrUpdateServer(credentials.Servers, server), credentialProvider.credentials(credentials); - var result = { - Servers: [] - }; - result.ApiClient = self._getOrAddApiClient(server, serverUrl), result.ApiClient.setSystemInfo(systemInfo), result.State = server.AccessToken && !1 !== options.enableAutoLogin ? "SignedIn" : "ServerSignIn", result.Servers.push(server), result.ApiClient.enableAutomaticBitrateDetection = options.enableAutomaticBitrateDetection, result.ApiClient.updateServerInfo(server, serverUrl); - var resolveActions = function() { - resolve(result), events.trigger(self, "connected", [result]) - }; - "SignedIn" === result.State ? (afterConnected(result.ApiClient, options), result.ApiClient.getCurrentUser().then(function(user) { - onLocalUserSignIn(server, serverUrl, user).then(resolveActions, resolveActions) - }, resolveActions)) : resolveActions() - } - - function getCacheKey(feature, apiClient, options) { - options = options || {}; - var viewOnly = options.viewOnly, - cacheKey = "regInfo-" + apiClient.serverId(); - return viewOnly && (cacheKey += "-viewonly"), cacheKey - } - - function addAppInfoToConnectRequest(request) { - request.headers = request.headers || {}, request.headers["X-Application"] = appName + "/" + appVersion - } - - function exchangePin(pinInfo) { - if (!pinInfo) throw new Error("pinInfo cannot be null"); - var request = { - type: "POST", - url: getConnectUrl("pin/authenticate"), - data: { - deviceId: pinInfo.DeviceId, - pin: pinInfo.Pin - }, - dataType: "json" - }; - return addAppInfoToConnectRequest(request), ajax(request) - } - console.log("Begin ConnectionManager constructor"); - var self = this; - this._apiClients = []; - var connectUser; - self.connectUser = function() { - return connectUser - }, self._minServerVersion = "3.2.33", self.appVersion = function() { - return appVersion - }, self.appName = function() { - return appName - }, self.capabilities = function() { - return capabilities - }, self.deviceId = function() { - return deviceId - }, self.credentialProvider = function() { - return credentialProvider - }, self.connectUserId = function() { - return credentialProvider.credentials().ConnectUserId - }, self.connectToken = function() { - return credentialProvider.credentials().ConnectAccessToken - }, self.getServerInfo = function(id) { - return credentialProvider.credentials().Servers.filter(function(s) { - return s.Id === id - })[0] - }, self.getLastUsedServer = function() { - var servers = credentialProvider.credentials().Servers; - return servers.sort(function(a, b) { - return (b.DateLastAccessed || 0) - (a.DateLastAccessed || 0) - }), servers.length ? servers[0] : null - }, self.addApiClient = function(apiClient) { - self._apiClients.push(apiClient); - var existingServers = credentialProvider.credentials().Servers.filter(function(s) { - return stringEqualsIgnoreCase(s.ManualAddress, apiClient.serverAddress()) || stringEqualsIgnoreCase(s.LocalAddress, apiClient.serverAddress()) || stringEqualsIgnoreCase(s.RemoteAddress, apiClient.serverAddress()) - }), - existingServer = existingServers.length ? existingServers[0] : apiClient.serverInfo(); - if (existingServer.DateLastAccessed = (new Date).getTime(), existingServer.LastConnectionMode = ConnectionMode.Manual, existingServer.ManualAddress = apiClient.serverAddress(), apiClient.manualAddressOnly && (existingServer.manualAddressOnly = !0), apiClient.serverInfo(existingServer), apiClient.onAuthenticated = function(instance, result) { - return onAuthenticated(instance, result, {}, !0) - }, !existingServers.length) { - var credentials = credentialProvider.credentials(); - credentials.Servers = [existingServer], credentialProvider.credentials(credentials) - } - events.trigger(self, "apiclientcreated", [apiClient]) - }, self.clearData = function() { - console.log("connection manager clearing data"), connectUser = null; - var credentials = credentialProvider.credentials(); - credentials.ConnectAccessToken = null, credentials.ConnectUserId = null, credentials.Servers = [], credentialProvider.credentials(credentials) - }, self._getOrAddApiClient = function(server, serverUrl) { - var apiClient = self.getApiClient(server.Id); - return apiClient || (apiClient = new apiClientFactory(serverUrl, appName, appVersion, deviceName, deviceId, devicePixelRatio), self._apiClients.push(apiClient), apiClient.serverInfo(server), apiClient.onAuthenticated = function(instance, result) { - return onAuthenticated(instance, result, {}, !0) - }, events.trigger(self, "apiclientcreated", [apiClient])), console.log("returning instance from getOrAddApiClient"), apiClient - }, self.getOrCreateApiClient = function(serverId) { - var credentials = credentialProvider.credentials(), - servers = credentials.Servers.filter(function(s) { - return stringEqualsIgnoreCase(s.Id, serverId) - }); - if (!servers.length) throw new Error("Server not found: " + serverId); - var server = servers[0]; - return self._getOrAddApiClient(server, getServerAddress(server, server.LastConnectionMode)) - }, self.user = function(apiClient) { - return new Promise(function(resolve, reject) { - function onLocalUserDone(e) { - var image = getImageUrl(localUser); - resolve({ - localUser: localUser, - name: connectUser ? connectUser.Name : localUser ? localUser.Name : null, - imageUrl: image.url, - supportsImageParams: image.supportsParams, - connectUser: connectUser - }) - } - - function onEnsureConnectUserDone() { - apiClient && apiClient.getCurrentUserId() ? apiClient.getCurrentUser().then(function(u) { - localUser = u, onLocalUserDone() - }, onLocalUserDone) : onLocalUserDone() - } - var localUser, credentials = credentialProvider.credentials(); - !credentials.ConnectUserId || !credentials.ConnectAccessToken || apiClient && apiClient.getCurrentUserId() ? onEnsureConnectUserDone() : ensureConnectUser(credentials).then(onEnsureConnectUserDone, onEnsureConnectUserDone) - }) - }, self.logout = function() { - console.log("begin connectionManager loguot"); - for (var promises = [], i = 0, length = self._apiClients.length; i < length; i++) { - var apiClient = self._apiClients[i]; - apiClient.accessToken() && promises.push(logoutOfServer(apiClient)) - } - return Promise.all(promises).then(function() { - for (var credentials = credentialProvider.credentials(), servers = credentials.Servers.filter(function(u) { - return "Guest" !== u.UserLinkType - }), j = 0, numServers = servers.length; j < numServers; j++) { - var server = servers[j]; - server.UserId = null, server.AccessToken = null, server.ExchangeToken = null - } - credentials.Servers = servers, credentials.ConnectAccessToken = null, credentials.ConnectUserId = null, credentialProvider.credentials(credentials), connectUser && (connectUser = null, events.trigger(self, "connectusersignedout")) - }) - }, self.getSavedServers = function() { - var credentials = credentialProvider.credentials(), - servers = credentials.Servers.slice(0); - return servers.sort(function(a, b) { - return (b.DateLastAccessed || 0) - (a.DateLastAccessed || 0) - }), servers - }, self.getAvailableServers = function() { - console.log("Begin getAvailableServers"); - var credentials = credentialProvider.credentials(); - return Promise.all([getConnectServers(credentials), findServers()]).then(function(responses) { - var connectServers = responses[0], - foundServers = responses[1], - servers = credentials.Servers.slice(0); - return mergeServers(credentialProvider, servers, foundServers), mergeServers(credentialProvider, servers, connectServers), servers = filterServers(servers, connectServers), servers.sort(function(a, b) { - return (b.DateLastAccessed || 0) - (a.DateLastAccessed || 0) - }), credentials.Servers = servers, credentialProvider.credentials(credentials), servers - }) - }, self.connectToServers = function(servers, options) { - console.log("Begin connectToServers, with " + servers.length + " servers"); - var firstServer = servers.length ? servers[0] : null; - return firstServer ? self.connectToServer(firstServer, options).then(function(result) { - return "Unavailable" === result.State && (result.State = "ServerSelection"), console.log("resolving connectToServers with result.State: " + result.State), result - }) : Promise.resolve({ - Servers: servers, - State: servers.length || self.connectUser() ? "ServerSelection" : "ConnectSignIn", - ConnectUser: self.connectUser() - }) - }, self.connectToServer = function(server, options) { - return console.log("begin connectToServer"), new Promise(function(resolve, reject) { - options = options || {}, tryReconnect(server).then(function(result) { - var serverUrl = result.url, - connectionMode = result.connectionMode; - result = result.data, 1 === compareVersions(self.minServerVersion(), result.Version) ? (console.log("minServerVersion requirement not met. Server version: " + result.Version), resolve({ - State: "ServerUpdateNeeded", - Servers: [server] - })) : server.Id && result.Id !== server.Id ? (console.log("http request succeeded, but found a different server Id than what was expected"), resolveFailure(self, resolve)) : onSuccessfulConnection(server, result, connectionMode, serverUrl, options, resolve) - }, function() { - resolveFailure(self, resolve) - }) - }) - }, self.connectToAddress = function(address, options) { - function onFail() { - return console.log("connectToAddress " + address + " failed"), Promise.resolve({ - State: "Unavailable", - ConnectUser: instance.connectUser() - }) - } - if (!address) return Promise.reject(); - address = normalizeAddress(address); - var instance = this, - server = { - ManualAddress: address, - LastConnectionMode: ConnectionMode.Manual - }; - return self.connectToServer(server, options).catch(onFail) - }, self.loginToConnect = function(username, password) { - return username && password ? ajax({ - type: "POST", - url: "https://connect.emby.media/service/user/authenticate", - data: { - nameOrEmail: username, - rawpw: password - }, - dataType: "json", - contentType: "application/x-www-form-urlencoded; charset=UTF-8", - headers: { - "X-Application": appName + "/" + appVersion - } - }).then(function(result) { - var credentials = credentialProvider.credentials(); - return credentials.ConnectAccessToken = result.AccessToken, credentials.ConnectUserId = result.User.Id, credentialProvider.credentials(credentials), onConnectUserSignIn(result.User), result - }) : Promise.reject() - }, self.signupForConnect = function(options) { - var email = options.email, - username = options.username, - password = options.password, - passwordConfirm = options.passwordConfirm; - if (!email) return Promise.reject({ - errorCode: "invalidinput" - }); - if (!username) return Promise.reject({ - errorCode: "invalidinput" - }); - if (!password) return Promise.reject({ - errorCode: "invalidinput" - }); - if (!passwordConfirm) return Promise.reject({ - errorCode: "passwordmatch" - }); - if (password !== passwordConfirm) return Promise.reject({ - errorCode: "passwordmatch" - }); - var data = { - email: email, - userName: username, - rawpw: password - }; - return options.grecaptcha && (data.grecaptcha = options.grecaptcha), ajax({ - type: "POST", - url: "https://connect.emby.media/service/register", - data: data, - dataType: "json", - contentType: "application/x-www-form-urlencoded; charset=UTF-8", - headers: { - "X-Application": appName + "/" + appVersion, - "X-CONNECT-TOKEN": "CONNECT-REGISTER" - } - }).catch(function(response) { - try { - return response.json() - } catch (err) { - throw err - } - }).then(function(result) { - if (result && result.Status) return "SUCCESS" === result.Status ? Promise.resolve(result) : Promise.reject({ - errorCode: result.Status - }); - Promise.reject() - }) - }, self.getUserInvitations = function() { - var connectToken = self.connectToken(); - if (!connectToken) throw new Error("null connectToken"); - if (!self.connectUserId()) throw new Error("null connectUserId"); - return ajax({ - type: "GET", - url: "https://connect.emby.media/service/servers?userId=" + self.connectUserId() + "&status=Waiting", - dataType: "json", - headers: { - "X-Connect-UserToken": connectToken, - "X-Application": appName + "/" + appVersion - } - }) - }, self.deleteServer = function(serverId) { - if (!serverId) throw new Error("null serverId"); - var server = credentialProvider.credentials().Servers.filter(function(s) { - return s.Id === serverId - }); - return server = server.length ? server[0] : null, new Promise(function(resolve, reject) { - function onDone() { - var credentials = credentialProvider.credentials(); - credentials.Servers = credentials.Servers.filter(function(s) { - return s.Id !== serverId - }), credentialProvider.credentials(credentials), resolve() - } - if (!server.ConnectServerId) return void onDone(); - var connectToken = self.connectToken(), - connectUserId = self.connectUserId(); - if (!connectToken || !connectUserId) return void onDone(); - ajax({ - type: "DELETE", - url: "https://connect.emby.media/service/serverAuthorizations?serverId=" + server.ConnectServerId + "&userId=" + connectUserId, - headers: { - "X-Connect-UserToken": connectToken, - "X-Application": appName + "/" + appVersion + console.log("tryReconnect: " + addressesStrings.join("|")); + return new Promise(function (resolve, reject) { + var state = {}; + state.numAddresses = addresses.length; + state.rejects = 0; + addresses.map(function (url) { + setTimeout(function () { + if (!state.resolved) { + getTryConnectPromise(url.url, url.mode, state, resolve, reject); } - }).then(onDone, onDone) - }) - }, self.rejectServer = function(serverId) { - var connectToken = self.connectToken(); - if (!serverId) throw new Error("null serverId"); - if (!connectToken) throw new Error("null connectToken"); - if (!self.connectUserId()) throw new Error("null connectUserId"); - var url = "https://connect.emby.media/service/serverAuthorizations?serverId=" + serverId + "&userId=" + self.connectUserId(); - return fetch(url, { - method: "DELETE", - headers: { - "X-Connect-UserToken": connectToken, - "X-Application": appName + "/" + appVersion - } - }) - }, self.acceptServer = function(serverId) { - var connectToken = self.connectToken(); - if (!serverId) throw new Error("null serverId"); - if (!connectToken) throw new Error("null connectToken"); - if (!self.connectUserId()) throw new Error("null connectUserId"); - return ajax({ - type: "GET", - url: "https://connect.emby.media/service/ServerAuthorizations/accept?serverId=" + serverId + "&userId=" + self.connectUserId(), - headers: { - "X-Connect-UserToken": connectToken, - "X-Application": appName + "/" + appVersion - } - }) - }, self.resetRegistrationInfo = function(apiClient) { - var cacheKey = getCacheKey("themes", apiClient, { - viewOnly: !0 + }, url.timeout); }); - appStorage.removeItem(cacheKey), cacheKey = getCacheKey("themes", apiClient, { - viewOnly: !1 - }), appStorage.removeItem(cacheKey) - }, self.getRegistrationInfo = function(feature, apiClient, options) { - var cacheKey = getCacheKey(feature, apiClient, options); - appStorage.setItem(cacheKey, JSON.stringify({ - lastValidDate: new Date().getTime(), - deviceId: self.deviceId() - })); - return Promise.resolve(); - }, self.createPin = function() { - var request = { - type: "POST", - url: getConnectUrl("pin"), - data: { - deviceId: deviceId - }, - dataType: "json" + }); + } + + function onSuccessfulConnection(server, systemInfo, connectionMode, serverUrl, options, resolve) { + var credentials = credentialProvider.credentials(); + options = options || {}; + + if (false !== options.enableAutoLogin) { + afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, true, options, resolve); + } + } + + function afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, verifyLocalAuthentication, options, resolve) { + options = options || {}; + if (false === options.enableAutoLogin) { + server.UserId = null; + server.AccessToken = null; + } else if (verifyLocalAuthentication && server.AccessToken && false !== options.enableAutoLogin) { + return void validateAuthentication(server, serverUrl).then(function () { + afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, false, options, resolve); + }); + } + + updateServerInfo(server, systemInfo); + server.LastConnectionMode = connectionMode; + + if (false !== options.updateDateLastAccessed) { + server.DateLastAccessed = new Date().getTime(); + } + + credentialProvider.addOrUpdateServer(credentials.Servers, server); + credentialProvider.credentials(credentials); + var result = { + Servers: [] + }; + result.ApiClient = self._getOrAddApiClient(server, serverUrl); + result.ApiClient.setSystemInfo(systemInfo); + result.State = server.AccessToken && false !== options.enableAutoLogin ? "SignedIn" : "ServerSignIn"; + result.Servers.push(server); + result.ApiClient.enableAutomaticBitrateDetection = options.enableAutomaticBitrateDetection; + result.ApiClient.updateServerInfo(server, serverUrl); + + var resolveActions = function () { + resolve(result); + events.trigger(self, "connected", [result]); + }; + + if ("SignedIn" === result.State) { + afterConnected(result.ApiClient, options); + result.ApiClient.getCurrentUser().then(function (user) { + onLocalUserSignIn(server, serverUrl, user).then(resolveActions, resolveActions); + }, resolveActions); + } else { + resolveActions(); + } + } + + console.log("Begin ConnectionManager constructor"); + var self = this; + this._apiClients = []; + self._minServerVersion = "3.2.33"; + + self.appVersion = function () { + return appVersion; + }; + + self.appName = function () { + return appName; + }; + + self.capabilities = function () { + return capabilities; + }; + + self.deviceId = function () { + return deviceId; + }; + + self.credentialProvider = function () { + return credentialProvider; + }; + + self.getServerInfo = function (id) { + return credentialProvider.credentials().Servers.filter(function (s) { + return s.Id === id; + })[0]; + }; + + self.getLastUsedServer = function () { + var servers = credentialProvider.credentials().Servers; + servers.sort(function (a, b) { + return (b.DateLastAccessed || 0) - (a.DateLastAccessed || 0); + }); + + if (servers.length) { + return servers[0]; + } + + return null; + }; + + self.addApiClient = function (apiClient) { + self._apiClients.push(apiClient); + + var existingServers = credentialProvider.credentials().Servers.filter(function (s) { + return stringEqualsIgnoreCase(s.ManualAddress, apiClient.serverAddress()) || stringEqualsIgnoreCase(s.LocalAddress, apiClient.serverAddress()) || stringEqualsIgnoreCase(s.RemoteAddress, apiClient.serverAddress()); + }); + var existingServer = existingServers.length ? existingServers[0] : apiClient.serverInfo(); + + existingServer.DateLastAccessed = new Date().getTime(); + existingServer.LastConnectionMode = ConnectionMode.Manual; + existingServer.ManualAddress = apiClient.serverAddress(); + if (apiClient.manualAddressOnly) { + existingServer.manualAddressOnly = true; + } + apiClient.serverInfo(existingServer); + apiClient.onAuthenticated = function (instance, result) { + return onAuthenticated(instance, result, {}, true); + }; + if (!existingServers.length) { + var credentials = credentialProvider.credentials(); + credentials.Servers = [existingServer]; + credentialProvider.credentials(credentials); + } + + events.trigger(self, "apiclientcreated", [apiClient]); + }; + + self.clearData = function () { + console.log("connection manager clearing data"); + var credentials = credentialProvider.credentials(); + credentials.Servers = []; + credentialProvider.credentials(credentials); + }; + + self._getOrAddApiClient = function (server, serverUrl) { + var apiClient = self.getApiClient(server.Id); + + if (!apiClient) { + apiClient = new apiClientFactory(serverUrl, appName, appVersion, deviceName, deviceId, devicePixelRatio); + self._apiClients.push(apiClient); + apiClient.serverInfo(server); + apiClient.onAuthenticated = function (instance, result) { + return onAuthenticated(instance, result, {}, true); }; - return addAppInfoToConnectRequest(request), ajax(request) - }, self.getPinStatus = function(pinInfo) { - if (!pinInfo) throw new Error("pinInfo cannot be null"); - var queryString = { - deviceId: pinInfo.DeviceId, - pin: pinInfo.Pin - }, - request = { - type: "GET", - url: getConnectUrl("pin") + "?" + paramsToString(queryString), - dataType: "json" - }; - return addAppInfoToConnectRequest(request), ajax(request) - }, self.exchangePin = function(pinInfo) { - if (!pinInfo) throw new Error("pinInfo cannot be null"); - return exchangePin(pinInfo).then(function(result) { - var credentials = credentialProvider.credentials(); - return credentials.ConnectAccessToken = result.AccessToken, credentials.ConnectUserId = result.UserId, credentialProvider.credentials(credentials), ensureConnectUser(credentials) - }) + + events.trigger(self, "apiclientcreated", [apiClient]); + } + + console.log("returning instance from getOrAddApiClient"); + return apiClient; + }; + + self.getOrCreateApiClient = function (serverId) { + var credentials = credentialProvider.credentials(); + var servers = credentials.Servers.filter(function (s) { + return stringEqualsIgnoreCase(s.Id, serverId); + }); + + if (!servers.length) { + throw new Error("Server not found: " + serverId); + } + + var server = servers[0]; + return self._getOrAddApiClient(server, getServerAddress(server, server.LastConnectionMode)); + }; + + self.user = function (apiClient) { + return new Promise(function (resolve, reject) { + function onLocalUserDone(e) { + if (apiClient && apiClient.getCurrentUserId()) { + apiClient.getCurrentUser().then(function (u) { + localUser = u; + var image = getImageUrl(localUser); + resolve({ + localUser: localUser, + name: localUser ? localUser.Name : null, + imageUrl: image.url, + supportsImageParams: image.supportsParams, + }); + }, onLocalUserDone); + } + } + var localUser; + if (apiClient && apiClient.getCurrentUserId()) { + onLocalUserDone(); + } + }); + }; + + self.logout = function () { + console.log("begin connectionManager loguot"); + var promises = []; + + for (var i = 0, length = self._apiClients.length; i < length; i++) { + var apiClient = self._apiClients[i]; + + if (apiClient.accessToken()) { + promises.push(logoutOfServer(apiClient)); + } + } + + return Promise.all(promises).then(function () { + var credentials = credentialProvider.credentials(); + var servers = credentials.Servers.filter(function (u) { + return "Guest" !== u.UserLinkType; + }); + + for (var j = 0, numServers = servers.length; j < numServers; j++) { + var server = servers[j]; + server.UserId = null; + server.AccessToken = null; + server.ExchangeToken = null; + } + }); + }; + + self.getSavedServers = function () { + var credentials = credentialProvider.credentials(); + var servers = credentials.Servers.slice(0); + servers.sort(function (a, b) { + return (b.DateLastAccessed || 0) - (a.DateLastAccessed || 0); + }); + return servers; + }; + + self.getAvailableServers = function () { + console.log("Begin getAvailableServers"); + var credentials = credentialProvider.credentials(); + return Promise.all([findServers()]).then(function (responses) { + var foundServers = responses[0]; + var servers = credentials.Servers.slice(0); + mergeServers(credentialProvider, servers, foundServers); + servers.sort(function (a, b) { + return (b.DateLastAccessed || 0) - (a.DateLastAccessed || 0); + }); + credentials.Servers = servers; + credentialProvider.credentials(credentials); + return servers; + }); + }; + + self.connectToServers = function (servers, options) { + console.log("Begin connectToServers, with " + servers.length + " servers"); + var firstServer = servers.length ? servers[0] : null; + + if (firstServer) { + return self.connectToServer(firstServer, options).then(function (result) { + if ("Unavailable" === result.State) { + result.State = "ServerSelection"; + } + + console.log("resolving connectToServers with result.State: " + result.State); + return result; + }); } }; - return ConnectionManager.prototype.connect = function(options) { + + self.connectToServer = function (server, options) { + console.log("begin connectToServer"); + return new Promise(function (resolve, reject) { + options = options || {}; + tryReconnect(server).then(function (result) { + var serverUrl = result.url; + var connectionMode = result.connectionMode; + result = result.data; + + if (1 === compareVersions(self.minServerVersion(), result.Version)) { + console.log("minServerVersion requirement not met. Server version: " + result.Version); + resolve({ + State: "ServerUpdateNeeded", + Servers: [server] + }); + } else { + if (server.Id && result.Id !== server.Id) { + console.log("http request succeeded, but found a different server Id than what was expected"); + resolveFailure(self, resolve); + } else { + onSuccessfulConnection(server, result, connectionMode, serverUrl, options, resolve); + } + } + }, function () { + resolveFailure(self, resolve); + }); + }); + }; + + self.connectToAddress = function (address, options) { + function onFail() { + console.log("connectToAddress " + address + " failed"); + return Promise.resolve({ + State: "Unavailable", + }); + } + + if (!address) { + return Promise.reject(); + } + + address = normalizeAddress(address); + var instance = this; + var server = { + ManualAddress: address, + LastConnectionMode: ConnectionMode.Manual + }; + return self.connectToServer(server, options).catch(onFail); + }; + + self.deleteServer = function (serverId) { + if (!serverId) { + throw new Error("null serverId"); + } + + var server = credentialProvider.credentials().Servers.filter(function (s) { + return s.Id === serverId; + }); + server = server.length ? server[0] : null; + return new Promise(function (resolve, reject) { + function onDone() { + var credentials = credentialProvider.credentials(); + credentials.Servers = credentials.Servers.filter(function (s) { + return s.Id !== serverId; + }); + credentialProvider.credentials(credentials); + resolve(); + } + + if (!server.ConnectServerId) { + return void onDone(); + } + }); + }; + }; + + ConnectionManager.prototype.connect = function (options) { console.log("Begin connect"); var instance = this; - return instance.getAvailableServers().then(function(servers) { - return instance.connectToServers(servers, options) - }) - }, ConnectionManager.prototype.isLoggedIntoConnect = function() { - return !(!this.connectToken() || !this.connectUserId()) - }, ConnectionManager.prototype.getApiClients = function() { - for (var servers = this.getSavedServers(), i = 0, length = servers.length; i < length; i++) { + return instance.getAvailableServers().then(function (servers) { + return instance.connectToServers(servers, options); + }); + }; + + ConnectionManager.prototype.getApiClients = function () { + var servers = this.getSavedServers(); + + for (var i = 0, length = servers.length; i < length; i++) { var server = servers[i]; - server.Id && this._getOrAddApiClient(server, getServerAddress(server, server.LastConnectionMode)) - } - return this._apiClients - }, ConnectionManager.prototype.getApiClient = function(item) { - if (!item) throw new Error("item or serverId cannot be null"); - return item.ServerId && (item = item.ServerId), this._apiClients.filter(function(a) { - var serverInfo = a.serverInfo(); - return !serverInfo || serverInfo.Id === item - })[0] - }, ConnectionManager.prototype.minServerVersion = function(val) { - return val && (this._minServerVersion = val), this._minServerVersion - }, ConnectionManager.prototype.handleMessageReceived = function(msg) { - var serverId = msg.ServerId; - if (serverId) { - var apiClient = this.getApiClient(serverId); - if (apiClient) { - if ("string" == typeof msg.Data) try { - msg.Data = JSON.parse(msg.Data) - } catch (err) {} - apiClient.handleMessageReceived(msg) + + if (server.Id) { + this._getOrAddApiClient(server, getServerAddress(server, server.LastConnectionMode)); } } - }, ConnectionManager + + return this._apiClients; + }; + + ConnectionManager.prototype.getApiClient = function (item) { + if (!item) { + throw new Error("item or serverId cannot be null"); + } + + if (item.ServerId) { + item = item.ServerId; + } + + return this._apiClients.filter(function (a) { + var serverInfo = a.serverInfo(); + return !serverInfo || serverInfo.Id === item; + })[0]; + }; + + ConnectionManager.prototype.minServerVersion = function (val) { + if (val) { + this._minServerVersion = val; + } + + return this._minServerVersion; + }; + + ConnectionManager.prototype.handleMessageReceived = function (msg) { + var serverId = msg.ServerId; + + if (serverId) { + var apiClient = this.getApiClient(serverId); + + if (apiClient) { + if ("string" == typeof msg.Data) { + try { + msg.Data = JSON.parse(msg.Data); + } catch (err) {} + } + + apiClient.handleMessageReceived(msg); + } + } + }; + + return ConnectionManager; }); diff --git a/src/bower_components/requirejs/require.js b/src/bower_components/requirejs/require.js deleted file mode 100644 index 71ac94c3b5..0000000000 --- a/src/bower_components/requirejs/require.js +++ /dev/null @@ -1,607 +0,0 @@ -var requirejs, require, define; -! function(global, setTimeout) { - function commentReplace(match, singlePrefix) { - return singlePrefix || "" - } - - function isFunction(it) { - return "[object Function]" === ostring.call(it) - } - - function isArray(it) { - return "[object Array]" === ostring.call(it) - } - - function each(ary, func) { - if (ary) { - var i; - for (i = 0; i < ary.length && (!ary[i] || !func(ary[i], i, ary)); i += 1); - } - } - - function eachReverse(ary, func) { - if (ary) { - var i; - for (i = ary.length - 1; i > -1 && (!ary[i] || !func(ary[i], i, ary)); i -= 1); - } - } - - function hasProp(obj, prop) { - return hasOwn.call(obj, prop) - } - - function getOwn(obj, prop) { - return hasProp(obj, prop) && obj[prop] - } - - function eachProp(obj, func) { - var prop; - for (prop in obj) - if (hasProp(obj, prop) && func(obj[prop], prop)) break - } - - function mixin(target, source, force, deepStringMixin) { - return source && eachProp(source, function(value, prop) { - !force && hasProp(target, prop) || (!deepStringMixin || "object" != typeof value || !value || isArray(value) || isFunction(value) || value instanceof RegExp ? target[prop] = value : (target[prop] || (target[prop] = {}), mixin(target[prop], value, force, deepStringMixin))) - }), target - } - - function bind(obj, fn) { - return function() { - return fn.apply(obj, arguments) - } - } - - function scripts() { - return document.getElementsByTagName("script") - } - - function defaultOnError(err) { - throw err - } - - function getGlobal(value) { - if (!value) return value; - var g = global; - return each(value.split("."), function(part) { - g = g[part] - }), g - } - - function makeError(id, msg, err, requireModules) { - var e = new Error(msg + "\nhttp://requirejs.org/docs/errors.html#" + id); - return e.requireType = id, e.requireModules = requireModules, err && (e.originalError = err), e - } - - function newContext(contextName) { - function trimDots(ary) { - var i, part; - for (i = 0; i < ary.length; i++) - if ("." === (part = ary[i])) ary.splice(i, 1), i -= 1; - else if (".." === part) { - if (0 === i || 1 === i && ".." === ary[2] || ".." === ary[i - 1]) continue; - i > 0 && (ary.splice(i - 1, 2), i -= 2) - } - } - - function normalize(name, baseName, applyMap) { - var mapValue, nameParts, i, j, nameSegment, lastIndex, foundMap, foundI, foundStarMap, starI, normalizedBaseParts, baseParts = baseName && baseName.split("/"), - map = config.map, - starMap = map && map["*"]; - if (name && (name = name.split("/"), lastIndex = name.length - 1, config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex]) && (name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, "")), "." === name[0].charAt(0) && baseParts && (normalizedBaseParts = baseParts.slice(0, baseParts.length - 1), name = normalizedBaseParts.concat(name)), trimDots(name), name = name.join("/")), applyMap && map && (baseParts || starMap)) { - nameParts = name.split("/"); - outerLoop: for (i = nameParts.length; i > 0; i -= 1) { - if (nameSegment = nameParts.slice(0, i).join("/"), baseParts) - for (j = baseParts.length; j > 0; j -= 1) - if ((mapValue = getOwn(map, baseParts.slice(0, j).join("/"))) && (mapValue = getOwn(mapValue, nameSegment))) { - foundMap = mapValue, foundI = i; - break outerLoop - }! foundStarMap && starMap && getOwn(starMap, nameSegment) && (foundStarMap = getOwn(starMap, nameSegment), starI = i) - }!foundMap && foundStarMap && (foundMap = foundStarMap, foundI = starI), foundMap && (nameParts.splice(0, foundI, foundMap), name = nameParts.join("/")) - } - return getOwn(config.pkgs, name) || name - } - - function removeScript(name) { - isBrowser && each(scripts(), function(scriptNode) { - if (scriptNode.getAttribute("data-requiremodule") === name && scriptNode.getAttribute("data-requirecontext") === context.contextName) return scriptNode.parentNode.removeChild(scriptNode), !0 - }) - } - - function hasPathFallback(id) { - var pathConfig = getOwn(config.paths, id); - if (pathConfig && isArray(pathConfig) && pathConfig.length > 1) return pathConfig.shift(), context.require.undef(id), context.makeRequire(null, { - skipMap: !0 - })([id]), !0 - } - - function splitPrefix(name) { - var prefix, index = name ? name.indexOf("!") : -1; - return index > -1 && (prefix = name.substring(0, index), name = name.substring(index + 1, name.length)), [prefix, name] - } - - function makeModuleMap(name, parentModuleMap, isNormalized, applyMap) { - var url, pluginModule, suffix, nameParts, prefix = null, - parentName = parentModuleMap ? parentModuleMap.name : null, - originalName = name, - isDefine = !0, - normalizedName = ""; - return name || (isDefine = !1, name = "_@r" + (requireCounter += 1)), nameParts = splitPrefix(name), prefix = nameParts[0], name = nameParts[1], prefix && (prefix = normalize(prefix, parentName, applyMap), pluginModule = getOwn(defined, prefix)), name && (prefix ? normalizedName = isNormalized ? name : pluginModule && pluginModule.normalize ? pluginModule.normalize(name, function(name) { - return normalize(name, parentName, applyMap) - }) : -1 === name.indexOf("!") ? normalize(name, parentName, applyMap) : name : (normalizedName = normalize(name, parentName, applyMap), nameParts = splitPrefix(normalizedName), prefix = nameParts[0], normalizedName = nameParts[1], isNormalized = !0, url = context.nameToUrl(normalizedName))), suffix = !prefix || pluginModule || isNormalized ? "" : "_unnormalized" + (unnormalizedCounter += 1), { - prefix: prefix, - name: normalizedName, - parentMap: parentModuleMap, - unnormalized: !!suffix, - url: url, - originalName: originalName, - isDefine: isDefine, - id: (prefix ? prefix + "!" + normalizedName : normalizedName) + suffix - } - } - - function getModule(depMap) { - var id = depMap.id, - mod = getOwn(registry, id); - return mod || (mod = registry[id] = new context.Module(depMap)), mod - } - - function on(depMap, name, fn) { - var id = depMap.id, - mod = getOwn(registry, id); - !hasProp(defined, id) || mod && !mod.defineEmitComplete ? (mod = getModule(depMap), mod.error && "error" === name ? fn(mod.error) : mod.on(name, fn)) : "defined" === name && fn(defined[id]) - } - - function onError(err, errback) { - var ids = err.requireModules, - notified = !1; - errback ? errback(err) : (each(ids, function(id) { - var mod = getOwn(registry, id); - mod && (mod.error = err, mod.events.error && (notified = !0, mod.emit("error", err))) - }), notified || req.onError(err)) - } - - function takeGlobalQueue() { - globalDefQueue.length && (each(globalDefQueue, function(queueItem) { - var id = queueItem[0]; - "string" == typeof id && (context.defQueueMap[id] = !0), defQueue.push(queueItem) - }), globalDefQueue = []) - } - - function cleanRegistry(id) { - delete registry[id], delete enabledRegistry[id] - } - - function breakCycle(mod, traced, processed) { - var id = mod.map.id; - mod.error ? mod.emit("error", mod.error) : (traced[id] = !0, each(mod.depMaps, function(depMap, i) { - var depId = depMap.id, - dep = getOwn(registry, depId); - !dep || mod.depMatched[i] || processed[depId] || (getOwn(traced, depId) ? (mod.defineDep(i, defined[depId]), mod.check()) : breakCycle(dep, traced, processed)) - }), processed[id] = !0) - } - - function checkLoaded() { - var err, usingPathFallback, waitInterval = 1e3 * config.waitSeconds, - expired = waitInterval && context.startTime + waitInterval < (new Date).getTime(), - noLoads = [], - reqCalls = [], - stillLoading = !1, - needCycleCheck = !0; - if (!inCheckLoaded) { - if (inCheckLoaded = !0, eachProp(enabledRegistry, function(mod) { - var map = mod.map, - modId = map.id; - if (mod.enabled && (map.isDefine || reqCalls.push(mod), !mod.error)) - if (!mod.inited && expired) hasPathFallback(modId) ? (usingPathFallback = !0, stillLoading = !0) : (noLoads.push(modId), removeScript(modId)); - else if (!mod.inited && mod.fetched && map.isDefine && (stillLoading = !0, !map.prefix)) return needCycleCheck = !1 - }), expired && noLoads.length) return err = makeError("timeout", "Load timeout for modules: " + noLoads, null, noLoads), err.contextName = context.contextName, onError(err); - needCycleCheck && each(reqCalls, function(mod) { - breakCycle(mod, {}, {}) - }), expired && !usingPathFallback || !stillLoading || !isBrowser && !isWebWorker || checkLoadedTimeoutId || (checkLoadedTimeoutId = setTimeout(function() { - checkLoadedTimeoutId = 0, checkLoaded() - }, 50)), inCheckLoaded = !1 - } - } - - function callGetModule(args) { - hasProp(defined, args[0]) || getModule(makeModuleMap(args[0], null, !0)).init(args[1], args[2]) - } - - function removeListener(node, func, name, ieName) { - node.detachEvent && !isOpera ? ieName && node.detachEvent(ieName, func) : node.removeEventListener(name, func, !1) - } - - function getScriptData(evt) { - var node = evt.currentTarget || evt.srcElement; - return removeListener(node, context.onScriptLoad, "load", "onreadystatechange"), removeListener(node, context.onScriptError, "error"), { - node: node, - id: node && node.getAttribute("data-requiremodule") - } - } - - function intakeDefines() { - var args; - for (takeGlobalQueue(); defQueue.length;) { - if (args = defQueue.shift(), null === args[0]) return onError(makeError("mismatch", "Mismatched anonymous define() module: " + args[args.length - 1])); - callGetModule(args) - } - context.defQueueMap = {} - } - var inCheckLoaded, Module, context, handlers, checkLoadedTimeoutId, config = { - waitSeconds: 7, - baseUrl: "./", - paths: {}, - bundles: {}, - pkgs: {}, - shim: {}, - config: {} - }, - registry = {}, - enabledRegistry = {}, - undefEvents = {}, - defQueue = [], - defined = {}, - urlFetched = {}, - bundlesMap = {}, - requireCounter = 1, - unnormalizedCounter = 1; - return handlers = { - require: function(mod) { - return mod.require ? mod.require : mod.require = context.makeRequire(mod.map) - }, - exports: function(mod) { - if (mod.usingExports = !0, mod.map.isDefine) return mod.exports ? defined[mod.map.id] = mod.exports : mod.exports = defined[mod.map.id] = {} - }, - module: function(mod) { - return mod.module ? mod.module : mod.module = { - id: mod.map.id, - uri: mod.map.url, - config: function() { - return getOwn(config.config, mod.map.id) || {} - }, - exports: mod.exports || (mod.exports = {}) - } - } - }, Module = function(map) { - this.events = getOwn(undefEvents, map.id) || {}, this.map = map, this.shim = getOwn(config.shim, map.id), this.depExports = [], this.depMaps = [], this.depMatched = [], this.pluginMaps = {}, this.depCount = 0 - }, Module.prototype = { - init: function(depMaps, factory, errback, options) { - options = options || {}, this.inited || (this.factory = factory, errback ? this.on("error", errback) : this.events.error && (errback = bind(this, function(err) { - this.emit("error", err) - })), this.depMaps = depMaps && depMaps.slice(0), this.errback = errback, this.inited = !0, this.ignore = options.ignore, options.enabled || this.enabled ? this.enable() : this.check()) - }, - defineDep: function(i, depExports) { - this.depMatched[i] || (this.depMatched[i] = !0, this.depCount -= 1, this.depExports[i] = depExports) - }, - fetch: function() { - if (!this.fetched) { - this.fetched = !0, context.startTime = (new Date).getTime(); - var map = this.map; - if (!this.shim) return map.prefix ? this.callPlugin() : this.load(); - context.makeRequire(this.map, { - enableBuildCallback: !0 - })(this.shim.deps || [], bind(this, function() { - return map.prefix ? this.callPlugin() : this.load() - })) - } - }, - load: function() { - var url = this.map.url; - urlFetched[url] || (urlFetched[url] = !0, context.load(this.map.id, url)) - }, - check: function() { - if (this.enabled && !this.enabling) { - var err, cjsModule, id = this.map.id, - depExports = this.depExports, - exports = this.exports, - factory = this.factory; - if (this.inited) { - if (this.error) this.emit("error", this.error); - else if (!this.defining) { - if (this.defining = !0, this.depCount < 1 && !this.defined) { - if (isFunction(factory)) { - if (this.events.error && this.map.isDefine || req.onError !== defaultOnError) try { - exports = context.execCb(id, factory, depExports, exports) - } catch (e) { - err = e - } else exports = context.execCb(id, factory, depExports, exports); - if (this.map.isDefine && void 0 === exports && (cjsModule = this.module, cjsModule ? exports = cjsModule.exports : this.usingExports && (exports = this.exports)), err) return err.requireMap = this.map, err.requireModules = this.map.isDefine ? [this.map.id] : null, err.requireType = this.map.isDefine ? "define" : "require", onError(this.error = err) - } else exports = factory; - if (this.exports = exports, this.map.isDefine && !this.ignore && (defined[id] = exports, req.onResourceLoad)) { - var resLoadMaps = []; - each(this.depMaps, function(depMap) { - resLoadMaps.push(depMap.normalizedMap || depMap) - }), req.onResourceLoad(context, this.map, resLoadMaps) - } - cleanRegistry(id), this.defined = !0 - } - this.defining = !1, this.defined && !this.defineEmitted && (this.defineEmitted = !0, this.emit("defined", this.exports), this.defineEmitComplete = !0) - } - } else hasProp(context.defQueueMap, id) || this.fetch() - } - }, - callPlugin: function() { - var map = this.map, - id = map.id, - pluginMap = makeModuleMap(map.prefix); - this.depMaps.push(pluginMap), on(pluginMap, "defined", bind(this, function(plugin) { - var load, normalizedMap, normalizedMod, bundleId = getOwn(bundlesMap, this.map.id), - name = this.map.name, - parentName = this.map.parentMap ? this.map.parentMap.name : null, - localRequire = context.makeRequire(map.parentMap, { - enableBuildCallback: !0 - }); - return this.map.unnormalized ? (plugin.normalize && (name = plugin.normalize(name, function(name) { - return normalize(name, parentName, !0) - }) || ""), normalizedMap = makeModuleMap(map.prefix + "!" + name, this.map.parentMap, !0), on(normalizedMap, "defined", bind(this, function(value) { - this.map.normalizedMap = normalizedMap, this.init([], function() { - return value - }, null, { - enabled: !0, - ignore: !0 - }) - })), void((normalizedMod = getOwn(registry, normalizedMap.id)) && (this.depMaps.push(normalizedMap), this.events.error && normalizedMod.on("error", bind(this, function(err) { - this.emit("error", err) - })), normalizedMod.enable()))) : bundleId ? (this.map.url = context.nameToUrl(bundleId), void this.load()) : (load = bind(this, function(value) { - this.init([], function() { - return value - }, null, { - enabled: !0 - }) - }), load.error = bind(this, function(err) { - this.inited = !0, this.error = err, err.requireModules = [id], eachProp(registry, function(mod) { - 0 === mod.map.id.indexOf(id + "_unnormalized") && cleanRegistry(mod.map.id) - }), onError(err) - }), load.fromText = bind(this, function(text, textAlt) { - var moduleName = map.name, - moduleMap = makeModuleMap(moduleName), - hasInteractive = useInteractive; - textAlt && (text = textAlt), hasInteractive && (useInteractive = !1), getModule(moduleMap), hasProp(config.config, id) && (config.config[moduleName] = config.config[id]); - try { - req.exec(text) - } catch (e) { - return onError(makeError("fromtexteval", "fromText eval for " + id + " failed: " + e, e, [id])) - } - hasInteractive && (useInteractive = !0), this.depMaps.push(moduleMap), context.completeLoad(moduleName), localRequire([moduleName], load) - }), void plugin.load(map.name, localRequire, load, config)) - })), context.enable(pluginMap, this), this.pluginMaps[pluginMap.id] = pluginMap - }, - enable: function() { - enabledRegistry[this.map.id] = this, this.enabled = !0, this.enabling = !0, each(this.depMaps, bind(this, function(depMap, i) { - var id, mod, handler; - if ("string" == typeof depMap) { - if (depMap = makeModuleMap(depMap, this.map.isDefine ? this.map : this.map.parentMap, !1, !this.skipMap), this.depMaps[i] = depMap, handler = getOwn(handlers, depMap.id)) return void(this.depExports[i] = handler(this)); - this.depCount += 1, on(depMap, "defined", bind(this, function(depExports) { - this.undefed || (this.defineDep(i, depExports), this.check()) - })), this.errback ? on(depMap, "error", bind(this, this.errback)) : this.events.error && on(depMap, "error", bind(this, function(err) { - this.emit("error", err) - })) - } - id = depMap.id, mod = registry[id], hasProp(handlers, id) || !mod || mod.enabled || context.enable(depMap, this) - })), eachProp(this.pluginMaps, bind(this, function(pluginMap) { - var mod = getOwn(registry, pluginMap.id); - mod && !mod.enabled && context.enable(pluginMap, this) - })), this.enabling = !1, this.check() - }, - on: function(name, cb) { - var cbs = this.events[name]; - cbs || (cbs = this.events[name] = []), cbs.push(cb) - }, - emit: function(name, evt) { - each(this.events[name], function(cb) { - cb(evt) - }), "error" === name && delete this.events[name] - } - }, context = { - config: config, - contextName: contextName, - registry: registry, - defined: defined, - urlFetched: urlFetched, - defQueue: defQueue, - defQueueMap: {}, - Module: Module, - makeModuleMap: makeModuleMap, - nextTick: req.nextTick, - onError: onError, - configure: function(cfg) { - if (cfg.baseUrl && "/" !== cfg.baseUrl.charAt(cfg.baseUrl.length - 1) && (cfg.baseUrl += "/"), "string" == typeof cfg.urlArgs) { - var urlArgs = cfg.urlArgs; - cfg.urlArgs = function(id, url) { - return (-1 === url.indexOf("?") ? "?" : "&") + urlArgs - } - } - var shim = config.shim, - objs = { - paths: !0, - bundles: !0, - config: !0, - map: !0 - }; - eachProp(cfg, function(value, prop) { - objs[prop] ? (config[prop] || (config[prop] = {}), mixin(config[prop], value, !0, !0)) : config[prop] = value - }), cfg.bundles && eachProp(cfg.bundles, function(value, prop) { - each(value, function(v) { - v !== prop && (bundlesMap[v] = prop) - }) - }), cfg.shim && (eachProp(cfg.shim, function(value, id) { - isArray(value) && (value = { - deps: value - }), !value.exports && !value.init || value.exportsFn || (value.exportsFn = context.makeShimExports(value)), shim[id] = value - }), config.shim = shim), cfg.packages && each(cfg.packages, function(pkgObj) { - var location, name; - pkgObj = "string" == typeof pkgObj ? { - name: pkgObj - } : pkgObj, name = pkgObj.name, location = pkgObj.location, location && (config.paths[name] = pkgObj.location), config.pkgs[name] = pkgObj.name + "/" + (pkgObj.main || "main").replace(currDirRegExp, "").replace(jsSuffixRegExp, "") - }), eachProp(registry, function(mod, id) { - mod.inited || mod.map.unnormalized || (mod.map = makeModuleMap(id, null, !0)) - }), (cfg.deps || cfg.callback) && context.require(cfg.deps || [], cfg.callback) - }, - makeShimExports: function(value) { - function fn() { - var ret; - return value.init && (ret = value.init.apply(global, arguments)), ret || value.exports && getGlobal(value.exports) - } - return fn - }, - makeRequire: function(relMap, options) { - function localRequire(deps, callback, errback) { - var id, map, requireMod; - return options.enableBuildCallback && callback && isFunction(callback) && (callback.__requireJsBuild = !0), "string" == typeof deps ? isFunction(callback) ? onError(makeError("requireargs", "Invalid require call"), errback) : relMap && hasProp(handlers, deps) ? handlers[deps](registry[relMap.id]) : req.get ? req.get(context, deps, relMap, localRequire) : (map = makeModuleMap(deps, relMap, !1, !0), id = map.id, hasProp(defined, id) ? defined[id] : onError(makeError("notloaded", 'Module name "' + id + '" has not been loaded yet for context: ' + contextName + (relMap ? "" : ". Use require([])")))) : (intakeDefines(), context.nextTick(function() { - intakeDefines(), requireMod = getModule(makeModuleMap(null, relMap)), requireMod.skipMap = options.skipMap, requireMod.init(deps, callback, errback, { - enabled: !0 - }), checkLoaded() - }), localRequire) - } - return options = options || {}, mixin(localRequire, { - isBrowser: isBrowser, - toUrl: function(moduleNamePlusExt) { - var ext, index = moduleNamePlusExt.lastIndexOf("."), - segment = moduleNamePlusExt.split("/")[0], - isRelative = "." === segment || ".." === segment; - return -1 !== index && (!isRelative || index > 1) && (ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length), moduleNamePlusExt = moduleNamePlusExt.substring(0, index)), context.nameToUrl(normalize(moduleNamePlusExt, relMap && relMap.id, !0), ext, !0) - }, - defined: function(id) { - return hasProp(defined, makeModuleMap(id, relMap, !1, !0).id) - }, - specified: function(id) { - return id = makeModuleMap(id, relMap, !1, !0).id, hasProp(defined, id) || hasProp(registry, id) - } - }), relMap || (localRequire.undef = function(id) { - takeGlobalQueue(); - var map = makeModuleMap(id, relMap, !0), - mod = getOwn(registry, id); - mod.undefed = !0, removeScript(id), delete defined[id], delete urlFetched[map.url], delete undefEvents[id], eachReverse(defQueue, function(args, i) { - args[0] === id && defQueue.splice(i, 1) - }), delete context.defQueueMap[id], mod && (mod.events.defined && (undefEvents[id] = mod.events), cleanRegistry(id)) - }), localRequire - }, - enable: function(depMap) { - getOwn(registry, depMap.id) && getModule(depMap).enable() - }, - completeLoad: function(moduleName) { - var found, args, mod, shim = getOwn(config.shim, moduleName) || {}, - shExports = shim.exports; - for (takeGlobalQueue(); defQueue.length;) { - if (args = defQueue.shift(), null === args[0]) { - if (args[0] = moduleName, found) break; - found = !0 - } else args[0] === moduleName && (found = !0); - callGetModule(args) - } - if (context.defQueueMap = {}, mod = getOwn(registry, moduleName), !found && !hasProp(defined, moduleName) && mod && !mod.inited) { - if (!(!config.enforceDefine || shExports && getGlobal(shExports))) return hasPathFallback(moduleName) ? void 0 : onError(makeError("nodefine", "No define call for " + moduleName, null, [moduleName])); - callGetModule([moduleName, shim.deps || [], shim.exportsFn]) - } - checkLoaded() - }, - nameToUrl: function(moduleName, ext, skipExt) { - var paths, syms, i, parentModule, url, parentPath, bundleId, pkgMain = getOwn(config.pkgs, moduleName); - if (pkgMain && (moduleName = pkgMain), bundleId = getOwn(bundlesMap, moduleName)) return context.nameToUrl(bundleId, ext, skipExt); - if (req.jsExtRegExp.test(moduleName)) url = moduleName + (ext || ""); - else { - for (paths = config.paths, syms = moduleName.split("/"), i = syms.length; i > 0; i -= 1) - if (parentModule = syms.slice(0, i).join("/"), parentPath = getOwn(paths, parentModule)) { - isArray(parentPath) && (parentPath = parentPath[0]), syms.splice(0, i, parentPath); - break - } url = syms.join("/"), url += ext || (/^data\:|^blob\:|\?/.test(url) || skipExt ? "" : ".js"), url = ("/" === url.charAt(0) || url.match(/^[\w\+\.\-]+:/) ? "" : config.baseUrl) + url - } - return config.urlArgs && !/^blob\:/.test(url) ? url + config.urlArgs(moduleName, url) : url - }, - load: function(id, url) { - req.load(context, id, url) - }, - execCb: function(name, callback, args, exports) { - return callback.apply(exports, args) - }, - onScriptLoad: function(evt) { - if ("load" === evt.type || readyRegExp.test((evt.currentTarget || evt.srcElement).readyState)) { - interactiveScript = null; - var data = getScriptData(evt); - context.completeLoad(data.id) - } - }, - onScriptError: function(evt) { - var data = getScriptData(evt); - if (!hasPathFallback(data.id)) { - var parents = []; - return eachProp(registry, function(value, key) { - 0 !== key.indexOf("_@r") && each(value.depMaps, function(depMap) { - if (depMap.id === data.id) return parents.push(key), !0 - }) - }), onError(makeError("scripterror", 'Script error for "' + data.id + (parents.length ? '", needed by: ' + parents.join(", ") : '"'), evt, [data.id])) - } - } - }, context.require = context.makeRequire(), context - } - - function getInteractiveScript() { - return interactiveScript && "interactive" === interactiveScript.readyState ? interactiveScript : (eachReverse(scripts(), function(script) { - if ("interactive" === script.readyState) return interactiveScript = script - }), interactiveScript) - } - var req, s, head, baseElement, dataMain, src, interactiveScript, currentlyAddingScript, mainScript, subPath, version = "2.3.5", - commentRegExp = /\/\*[\s\S]*?\*\/|([^:"'=]|^)\/\/.*$/gm, - cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g, - jsSuffixRegExp = /\.js$/, - currDirRegExp = /^\.\//, - op = Object.prototype, - ostring = op.toString, - hasOwn = op.hasOwnProperty, - isBrowser = !("undefined" == typeof window || "undefined" == typeof navigator || !window.document), - isWebWorker = !isBrowser && "undefined" != typeof importScripts, - readyRegExp = isBrowser && "PLAYSTATION 3" === navigator.platform ? /^complete$/ : /^(complete|loaded)$/, - defContextName = "_", - isOpera = "undefined" != typeof opera && "[object Opera]" === opera.toString(), - contexts = {}, - cfg = {}, - globalDefQueue = [], - useInteractive = !1; - if (void 0 === define) { - if (void 0 !== requirejs) { - if (isFunction(requirejs)) return; - cfg = requirejs, requirejs = void 0 - } - void 0 === require || isFunction(require) || (cfg = require, require = void 0), req = requirejs = function(deps, callback, errback, optional) { - var context, config, contextName = defContextName; - return isArray(deps) || "string" == typeof deps || (config = deps, isArray(callback) ? (deps = callback, callback = errback, errback = optional) : deps = []), config && config.context && (contextName = config.context), context = getOwn(contexts, contextName), context || (context = contexts[contextName] = req.s.newContext(contextName)), config && context.configure(config), context.require(deps, callback, errback) - }, req.config = function(config) { - return req(config) - }, req.nextTick = void 0 !== setTimeout ? function(fn) { - setTimeout(fn, 4) - } : function(fn) { - fn() - }, require || (require = req), req.version = version, req.jsExtRegExp = /^\/|:|\?|\.js$/, req.isBrowser = isBrowser, s = req.s = { - contexts: contexts, - newContext: newContext - }, req({}), each(["toUrl", "undef", "defined", "specified"], function(prop) { - req[prop] = function() { - var ctx = contexts[defContextName]; - return ctx.require[prop].apply(ctx, arguments) - } - }), isBrowser && (head = s.head = document.getElementsByTagName("head")[0], (baseElement = document.getElementsByTagName("base")[0]) && (head = s.head = baseElement.parentNode)), req.onError = defaultOnError, req.createNode = function(config, moduleName, url) { - var node = config.xhtml ? document.createElementNS("http://www.w3.org/1999/xhtml", "html:script") : document.createElement("script"); - return node.type = config.scriptType || "text/javascript", node.charset = "utf-8", node.async = !0, node - }, req.load = function(context, moduleName, url) { - var node, config = context && context.config || {}; - if (isBrowser) return node = req.createNode(config, moduleName, url), node.setAttribute("data-requirecontext", context.contextName), node.setAttribute("data-requiremodule", moduleName), !node.attachEvent || node.attachEvent.toString && node.attachEvent.toString().indexOf("[native code") < 0 || isOpera ? (node.addEventListener("load", context.onScriptLoad, !1), node.addEventListener("error", context.onScriptError, !1)) : (useInteractive = !0, node.attachEvent("onreadystatechange", context.onScriptLoad)), node.src = url, config.onNodeCreated && config.onNodeCreated(node, config, moduleName, url), currentlyAddingScript = node, baseElement ? head.insertBefore(node, baseElement) : head.appendChild(node), currentlyAddingScript = null, node; - if (isWebWorker) try { - setTimeout(function() {}, 0), importScripts(url), context.completeLoad(moduleName) - } catch (e) { - context.onError(makeError("importscripts", "importScripts failed for " + moduleName + " at " + url, e, [moduleName])) - } - }, isBrowser && !cfg.skipDataMain && eachReverse(scripts(), function(script) { - if (head || (head = script.parentNode), dataMain = script.getAttribute("data-main")) return mainScript = dataMain, cfg.baseUrl || -1 !== mainScript.indexOf("!") || (src = mainScript.split("/"), mainScript = src.pop(), subPath = src.length ? src.join("/") + "/" : "./", cfg.baseUrl = subPath), mainScript = mainScript.replace(jsSuffixRegExp, ""), req.jsExtRegExp.test(mainScript) && (mainScript = dataMain), cfg.deps = cfg.deps ? cfg.deps.concat(mainScript) : [mainScript], !0 - }), define = function(name, deps, callback) { - var node, context; - "string" != typeof name && (callback = deps, deps = name, name = null), isArray(deps) || (callback = deps, deps = null), !deps && isFunction(callback) && (deps = [], callback.length && (callback.toString().replace(commentRegExp, commentReplace).replace(cjsRequireRegExp, function(match, dep) { - deps.push(dep) - }), deps = (1 === callback.length ? ["require"] : ["require", "exports", "module"]).concat(deps))), useInteractive && (node = currentlyAddingScript || getInteractiveScript()) && (name || (name = node.getAttribute("data-requiremodule")), context = contexts[node.getAttribute("data-requirecontext")]), context ? (context.defQueue.push([name, deps, callback]), context.defQueueMap[name] = !0) : globalDefQueue.push([name, deps, callback]) - }, define.amd = { - jQuery: !0 - }, req.exec = function(text) { - return eval(text) - }, req(cfg) - } -}(this, "undefined" == typeof setTimeout ? void 0 : setTimeout); \ No newline at end of file diff --git a/src/components/emby-tabs/emby-tabs.js b/src/components/emby-tabs/emby-tabs.js index d88b111060..4a0060cf88 100644 --- a/src/components/emby-tabs/emby-tabs.js +++ b/src/components/emby-tabs/emby-tabs.js @@ -10,23 +10,6 @@ define(['dom', 'scroller', 'browser', 'layoutManager', 'focusManager', 'register newButton.classList.add(activeButtonClass); } - function getFocusCallback(tabs, e) { - return function () { - onClick.call(tabs, e); - }; - } - - function onFocus(e) { - - if (layoutManager.tv) { - - if (this.focusTimeout) { - clearTimeout(this.focusTimeout); - } - this.focusTimeout = setTimeout(getFocusCallback(this, e), 700); - } - } - function getTabPanel(tabs, index) { return null; @@ -87,10 +70,6 @@ define(['dom', 'scroller', 'browser', 'layoutManager', 'focusManager', 'register function onClick(e) { - if (this.focusTimeout) { - clearTimeout(this.focusTimeout); - } - var tabs = this; var current = tabs.querySelector('.' + activeButtonClass); @@ -177,10 +156,6 @@ define(['dom', 'scroller', 'browser', 'layoutManager', 'focusManager', 'register dom.addEventListener(this, 'click', onClick, { passive: true }); - dom.addEventListener(this, 'focus', onFocus, { - passive: true, - capture: true - }); }; EmbyTabs.focus = function () { @@ -237,10 +212,6 @@ define(['dom', 'scroller', 'browser', 'layoutManager', 'focusManager', 'register dom.removeEventListener(this, 'click', onClick, { passive: true }); - dom.removeEventListener(this, 'focus', onFocus, { - passive: true, - capture: true - }); }; function getSelectedTabButton(elem) { diff --git a/src/components/homescreensettings/homescreensettings.js b/src/components/homescreensettings/homescreensettings.js index e881edbdbd..633437d26e 100644 --- a/src/components/homescreensettings/homescreensettings.js +++ b/src/components/homescreensettings/homescreensettings.js @@ -330,6 +330,7 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa if (next) { viewItem.parentNode.removeChild(viewItem); next.parentNode.insertBefore(viewItem, next.nextSibling); + focusManager.focus(e.target); } } else { @@ -339,6 +340,7 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa if (prev) { viewItem.parentNode.removeChild(viewItem); prev.parentNode.insertBefore(viewItem, prev); + focusManager.focus(e.target); } } } diff --git a/src/components/htmlvideoplayer/plugin.js b/src/components/htmlvideoplayer/plugin.js index d040c03bda..5b56649011 100644 --- a/src/components/htmlvideoplayer/plugin.js +++ b/src/components/htmlvideoplayer/plugin.js @@ -1043,7 +1043,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa video: videoElement, subUrl: getTextTrackUrl(track, item), fonts: attachments.map(i => i.DeliveryUrl), - workerUrl: appRouter.baseUrl() + "/node_modules/libass-wasm/dist/subtitles-octopus-worker.js", + workerUrl: appRouter.baseUrl() + "/libraries/subtitles-octopus-worker.js", onError: function() { htmlMediaHelper.onErrorInternal(self, 'mediadecodeerror') } diff --git a/src/controllers/addpluginpage.js b/src/controllers/addpluginpage.js index 0ecb65ab75..7930d6927b 100644 --- a/src/controllers/addpluginpage.js +++ b/src/controllers/addpluginpage.js @@ -1,31 +1,37 @@ -define(["jQuery", "loading", "libraryMenu", "globalize", "connectionManager", "emby-button"], function($, loading, libraryMenu, globalize, connectionManager) { +define(["jQuery", "loading", "libraryMenu", "globalize", "connectionManager", "emby-button"], function ($, loading, libraryMenu, globalize, connectionManager) { "use strict"; function populateHistory(packageInfo, page) { var html = ""; var length = Math.min(packageInfo.versions.length, 10); + for (var i = 0; i < length; i++) { var version = packageInfo.versions[i]; html += '

' + version.versionStr + " (" + version.classification + ")

"; html += '
' + version.description + "
"; } + $("#revisionHistory", page).html(html); } function populateVersions(packageInfo, page, installedPlugin) { var html = ""; + for (var i = 0; i < packageInfo.versions.length; i++) { var version = packageInfo.versions[i]; html += '"; } + var selectmenu = $("#selectVersion", page).html(html); + if (!installedPlugin) { $("#pCurrentVersion", page).hide().html(""); } - var packageVersion = packageInfo.versions.filter(function(current) { + + var packageVersion = packageInfo.versions.filter(function (current) { return "Release" == current.classification; })[0]; - packageVersion = packageVersion || packageInfo.versions.filter(function(current) { + packageVersion = packageVersion || packageInfo.versions.filter(function (current) { return "Beta" == current.classification; })[0]; @@ -36,12 +42,13 @@ define(["jQuery", "loading", "libraryMenu", "globalize", "connectionManager", "e } function renderPackage(pkg, installedPlugins, page) { - var installedPlugin = installedPlugins.filter(function(ip) { - return ip.Name == pkg.name + var installedPlugin = installedPlugins.filter(function (ip) { + return ip.Name == pkg.name; })[0]; populateVersions(pkg, page, installedPlugin); populateHistory(pkg, page); $(".pluginName", page).html(pkg.name); + if ("Server" == pkg.targetSystem) { $("#btnInstallDiv", page).removeClass("hide"); $("#nonServerMsg", page).hide(); @@ -52,60 +59,69 @@ define(["jQuery", "loading", "libraryMenu", "globalize", "connectionManager", "e var msg = globalize.translate("MessageInstallPluginFromApp"); $("#nonServerMsg", page).html(msg).show(); } + if (pkg.shortDescription) { $("#tagline", page).show().html(pkg.shortDescription); } else { $("#tagline", page).hide(); } + $("#overview", page).html(pkg.overview || ""); $("#developer", page).html(pkg.owner); + if (pkg.richDescUrl) { $("#pViewWebsite", page).show(); $("#pViewWebsite a", page).attr("href", pkg.richDescUrl); } else { $("#pViewWebsite", page).hide(); } + if (pkg.previewImage || pkg.thumbImage) { var img = pkg.previewImage ? pkg.previewImage : pkg.thumbImage; $("#pPreviewImage", page).show().html(""); } else { $("#pPreviewImage", page).hide().html(""); } + if (installedPlugin) { var currentVersionText = globalize.translate("MessageYouHaveVersionInstalled").replace("{0}", "" + installedPlugin.Version + ""); $("#pCurrentVersion", page).show().html(currentVersionText); } else { $("#pCurrentVersion", page).hide().html(""); } + loading.hide(); } function alertText(options) { - require(["alert"], function(alert) { - alert(options) - }) + require(["alert"], function (alert) { + alert(options); + }); } function performInstallation(page, packageName, guid, updateClass, version) { var developer = $("#developer", page).html().toLowerCase(); - var alertCallback = function() { + + var alertCallback = function () { loading.show(); page.querySelector("#btnInstall").disabled = true; - ApiClient.installPlugin(packageName, guid, updateClass, version).then(function() { + ApiClient.installPlugin(packageName, guid, updateClass, version).then(function () { loading.hide(); alertText(globalize.translate("PluginInstalledMessage")); }); }; + if (developer !== 'jellyfin') { loading.hide(); var msg = globalize.translate("MessagePluginInstallDisclaimer"); msg += "
"; msg += "
"; msg += globalize.translate("PleaseConfirmPluginInstallation"); - require(["confirm"], function(confirm) { - confirm(msg, globalize.translate("HeaderConfirmPluginInstallation")).then(function() { + + require(["confirm"], function (confirm) { + confirm(msg, globalize.translate("HeaderConfirmPluginInstallation")).then(function () { alertCallback(); - }, function() { + }, function () { console.log('plugin not installed'); }); }); @@ -114,18 +130,19 @@ define(["jQuery", "loading", "libraryMenu", "globalize", "connectionManager", "e } } - return function(view, params) { - $(".addPluginForm", view).on("submit", function() { + return function (view, params) { + $(".addPluginForm", view).on("submit", function () { loading.show(); var page = $(this).parents("#addPluginPage")[0]; var name = params.name; var guid = params.guid; - ApiClient.getInstalledPlugins().then(function(plugins) { - var installedPlugin = plugins.filter(function(plugin) { + ApiClient.getInstalledPlugins().then(function (plugins) { + var installedPlugin = plugins.filter(function (plugin) { return plugin.Name == name; })[0]; var vals = $("#selectVersion", page).val().split("|"); var version = vals[0]; + if (installedPlugin) { if (installedPlugin.Version === version) { loading.hide(); @@ -140,16 +157,16 @@ define(["jQuery", "loading", "libraryMenu", "globalize", "connectionManager", "e }); return false; }); - view.addEventListener("viewshow", function() { + view.addEventListener("viewshow", function () { var page = this; loading.show(); var name = params.name; var guid = params.guid; var promise1 = ApiClient.getPackageInfo(name, guid); var promise2 = ApiClient.getInstalledPlugins(); - Promise.all([promise1, promise2]).then(function(responses) { + Promise.all([promise1, promise2]).then(function (responses) { renderPackage(responses[0], responses[1], page); }); - }) - } + }); + }; }); diff --git a/src/controllers/addserver.js b/src/controllers/addserver.js index 6d596632b2..55b670f546 100644 --- a/src/controllers/addserver.js +++ b/src/controllers/addserver.js @@ -57,5 +57,5 @@ define(["appSettings", "loading", "browser", "emby-button"], function(appSetting appRouter.back(); }); } - } + }; }); diff --git a/src/controllers/apikeys.js b/src/controllers/apikeys.js index 3315e304e3..448ffa29a7 100644 --- a/src/controllers/apikeys.js +++ b/src/controllers/apikeys.js @@ -1,14 +1,14 @@ -define(["datetime", "loading", "libraryMenu", "dom", "globalize", "emby-button"], function(datetime, loading, libraryMenu, dom, globalize) { +define(["datetime", "loading", "libraryMenu", "dom", "globalize", "emby-button"], function (datetime, loading, libraryMenu, dom, globalize) { "use strict"; function revoke(page, key) { - require(["confirm"], function(confirm) { - confirm(globalize.translate("MessageConfirmRevokeApiKey"), globalize.translate("HeaderConfirmRevokeApiKey")).then(function() { + require(["confirm"], function (confirm) { + confirm(globalize.translate("MessageConfirmRevokeApiKey"), globalize.translate("HeaderConfirmRevokeApiKey")).then(function () { loading.show(); ApiClient.ajax({ type: "DELETE", url: ApiClient.getUrl("Auth/Keys/" + key) - }).then(function() { + }).then(function () { loadData(page); }); }); @@ -16,11 +16,23 @@ define(["datetime", "loading", "libraryMenu", "dom", "globalize", "emby-button"] } function renderKeys(page, keys) { - var rows = keys.map(function(item) { + var rows = keys.map(function (item) { var html = ""; - html += '', html += '', html += '", html += "", html += '', html += item.AccessToken, html += "", html += '', html += item.AppName || "", html += "", html += ''; - var date = datetime.parseISO8601Date(item.DateCreated, !0); - return html += datetime.toLocaleDateString(date) + " " + datetime.getDisplayTime(date), html += "", html += "" + html += ''; + html += ''; + html += '"; + html += ""; + html += ''; + html += item.AccessToken; + html += ""; + html += ''; + html += item.AppName || ""; + html += ""; + html += ''; + var date = datetime.parseISO8601Date(item.DateCreated, true); + html += datetime.toLocaleDateString(date) + " " + datetime.getDisplayTime(date); + html += ""; + return html += ""; }).join(""); page.querySelector(".resultBody").innerHTML = rows; loading.hide(); @@ -28,42 +40,44 @@ define(["datetime", "loading", "libraryMenu", "dom", "globalize", "emby-button"] function loadData(page) { loading.show(); - ApiClient.getJSON(ApiClient.getUrl("Auth/Keys")).then(function(result) { + ApiClient.getJSON(ApiClient.getUrl("Auth/Keys")).then(function (result) { renderKeys(page, result.Items); }); } function showNewKeyPrompt(page) { - require(["prompt"], function(prompt) { + require(["prompt"], function (prompt) { prompt({ title: globalize.translate("HeaderNewApiKey"), label: globalize.translate("LabelAppName"), description: globalize.translate("LabelAppNameExample") - }).then(function(value) { + }).then(function (value) { ApiClient.ajax({ type: "POST", url: ApiClient.getUrl("Auth/Keys", { App: value }) - }).then(function() { - loadData(page) - }) - }) - }) + }).then(function () { + loadData(page); + }); + }); + }); } - pageIdOn("pageinit", "apiKeysPage", function() { + pageIdOn("pageinit", "apiKeysPage", function () { var page = this; - page.querySelector(".btnNewKey").addEventListener("click", function() { - showNewKeyPrompt(page) + page.querySelector(".btnNewKey").addEventListener("click", function () { + showNewKeyPrompt(page); }); - page.querySelector(".tblApiKeys").addEventListener("click", function(e) { + page.querySelector(".tblApiKeys").addEventListener("click", function (e) { var btnRevoke = dom.parentWithClass(e.target, "btnRevoke"); - btnRevoke && revoke(page, btnRevoke.getAttribute("data-token")) + + if (btnRevoke) { + revoke(page, btnRevoke.getAttribute("data-token")); + } }); }); - - pageIdOn("pagebeforeshow", "apiKeysPage", function() { + pageIdOn("pagebeforeshow", "apiKeysPage", function () { loadData(this); - }) -}); \ No newline at end of file + }); +}); diff --git a/src/controllers/dashboardpage.js b/src/controllers/dashboardpage.js index 229befdeda..de86ffc2bd 100644 --- a/src/controllers/dashboardpage.js +++ b/src/controllers/dashboardpage.js @@ -5,8 +5,8 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa require(["alert"], function (alert) { var title; var text = []; - var displayPlayMethod = playMethodHelper.getDisplayPlayMethod(session); + if (displayPlayMethod === "DirectStream") { title = globalize.translate("DirectStreaming"); text.push(globalize.translate("DirectStreamHelp1")); @@ -15,6 +15,7 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa } else if (displayPlayMethod === "Transcode") { title = globalize.translate("Transcoding"); text.push(globalize.translate("MediaIsBeingConverted")); + if (session.TranscodingInfo && session.TranscodingInfo.TranscodeReasons && session.TranscodingInfo.TranscodeReasons.length) { text.push("
"); text.push(globalize.translate("LabelReasonForTranscoding")); @@ -23,6 +24,7 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa }); } } + alert({ text: text.join("
"), title: title @@ -73,6 +75,7 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa case "sendmessage": showSendMessageForm(btn, session); break; + case "transcodinginfo": showPlaybackInfo(btn, session); } @@ -124,6 +127,7 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa list.push(session); } } + return list; } @@ -139,7 +143,7 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa if (!result.Items.length) { view.querySelector(".activeRecordingsSection").classList.add("hide"); - return void (itemsContainer.innerHTML = ""); + return void(itemsContainer.innerHTML = ""); } view.querySelector(".activeRecordingsSection").classList.remove("hide"); @@ -165,13 +169,13 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa function reloadSystemInfo(view, apiClient) { apiClient.getSystemInfo().then(function (systemInfo) { view.querySelector("#serverName").innerHTML = globalize.translate("DashboardServerName", systemInfo.ServerName); - var localizedVersion = globalize.translate("DashboardVersionNumber", systemInfo.Version); + if (systemInfo.SystemUpdateLevel !== "Release") { localizedVersion += " " + systemInfo.SystemUpdateLevel; } - view.querySelector("#versionNumber").innerHTML = localizedVersion; + view.querySelector("#versionNumber").innerHTML = localizedVersion; view.querySelector("#operatingSystem").innerHTML = globalize.translate("DashboardOperatingSystem", systemInfo.OperatingSystem); view.querySelector("#architecture").innerHTML = globalize.translate("DashboardArchitecture", systemInfo.SystemArchitecture); @@ -226,14 +230,13 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa } else { var nowPlayingItem = session.NowPlayingItem; var className = "scalableCard card activeSession backdropCard backdropCard-scalable"; - html += '
'; html += '
'; html += '
'; html += '
'; html += '
'; - var imgUrl = DashboardPage.getNowPlayingImageUrl(nowPlayingItem); + if (imgUrl) { html += '
"; @@ -243,8 +246,8 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa html += '
'; html += '
'; - var clientImage = DashboardPage.getClientImage(session); + if (clientImage) { html += clientImage; } @@ -261,28 +264,36 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa html += '
'; } - html += '
' + html += '
'; var nowPlayingName = DashboardPage.getNowPlayingName(session); html += '
'; html += nowPlayingName.html; html += "
"; html += '
' + DashboardPage.getSessionNowPlayingTime(session) + "
"; - html += '
' + html += '
'; if (nowPlayingItem && nowPlayingItem.RunTimeTicks) { var percent = 100 * (session.PlayState.PositionTicks || 0) / nowPlayingItem.RunTimeTicks; - html += indicators.getProgressHtml(percent, { containerClass: "playbackProgress" }); + html += indicators.getProgressHtml(percent, { + containerClass: "playbackProgress" + }); } else { // need to leave the element in just in case the device starts playback - html += indicators.getProgressHtml(0, { containerClass: "playbackProgress hide" }); + html += indicators.getProgressHtml(0, { + containerClass: "playbackProgress hide" + }); } if (session.TranscodingInfo && session.TranscodingInfo.CompletionPercentage) { var percent = session.TranscodingInfo.CompletionPercentage.toFixed(1); - html += indicators.getProgressHtml(percent, { containerClass: "transcodingProgress" }); + html += indicators.getProgressHtml(percent, { + containerClass: "transcodingProgress" + }); } else { // same issue as playbackProgress element above - html += indicators.getProgressHtml(0, { containerClass: "transcodingProgress hide" }); + html += indicators.getProgressHtml(0, { + containerClass: "transcodingProgress hide" + }); } html += "
"; @@ -317,6 +328,7 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa parentElement.insertAdjacentHTML("beforeend", html); var deadSessionElem = parentElement.querySelector(".deadSession"); + if (deadSessionElem) { deadSessionElem.parentNode.removeChild(deadSessionElem); } @@ -340,9 +352,9 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa for (var i = 0, length = tasks.length; i < length; i++) { var task = tasks[i]; - html += "

"; html += task.Name + "
"; + if (task.State === "Running") { var progress = (task.CurrentProgressPercentage || 0).toFixed(1); html += ''; @@ -373,19 +385,24 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa var html = ""; var showTranscodingInfo = false; var displayPlayMethod = playMethodHelper.getDisplayPlayMethod(session); + if (displayPlayMethod === "DirectStream") { html += globalize.translate("DirectStreaming"); } else if (displayPlayMethod === "Transcode") { html += globalize.translate("Transcoding"); + if (session.TranscodingInfo && session.TranscodingInfo.Framerate) { html += " (" + session.TranscodingInfo.Framerate + " fps)"; } + showTranscodingInfo = true; } else if (displayPlayMethod === "DirectPlay") { html += globalize.translate("DirectPlaying"); } + if (showTranscodingInfo) { var line = []; + if (session.TranscodingInfo) { if (session.TranscodingInfo.Bitrate) { if (session.TranscodingInfo.Bitrate > 1e6) { @@ -493,6 +510,7 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa }, getUsersHtml: function (session) { var html = []; + if (session.UserId) { html.push(session.UserName); } @@ -516,8 +534,8 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa }, updateSession: function (row, session) { row.classList.remove("deadSession"); - var nowPlayingItem = session.NowPlayingItem; + if (nowPlayingItem) { row.classList.add("playingSession"); } else { @@ -537,6 +555,7 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa } var btnSessionPlayPause = row.querySelector(".btnSessionPlayPause"); + if (session.ServerId && nowPlayingItem && session.SupportsRemoteControl && session.DeviceId !== connectionManager.deviceId()) { btnSessionPlayPause.classList.remove("hide"); row.querySelector(".btnSessionStop").classList.remove("hide"); @@ -565,19 +584,29 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa } var playbackProgressElem = row.querySelector(".playbackProgress"); + if (nowPlayingItem && nowPlayingItem.RunTimeTicks) { var percent = 100 * (session.PlayState.PositionTicks || 0) / nowPlayingItem.RunTimeTicks; - playbackProgressElem.outerHTML = indicators.getProgressHtml(percent, { containerClass: "playbackProgress" }); + playbackProgressElem.outerHTML = indicators.getProgressHtml(percent, { + containerClass: "playbackProgress" + }); } else { - playbackProgressElem.outerHTML = indicators.getProgressHtml(0, { containerClass: "playbackProgress hide" }); + playbackProgressElem.outerHTML = indicators.getProgressHtml(0, { + containerClass: "playbackProgress hide" + }); } var transcodingProgress = row.querySelector(".transcodingProgress"); + if (session.TranscodingInfo && session.TranscodingInfo.CompletionPercentage) { var percent = session.TranscodingInfo.CompletionPercentage.toFixed(1); - transcodingProgress.outerHTML = indicators.getProgressHtml(percent, { containerClass: "transcodingProgress" }); + transcodingProgress.outerHTML = indicators.getProgressHtml(percent, { + containerClass: "transcodingProgress" + }); } else { - transcodingProgress.outerHTML = indicators.getProgressHtml(0, { containerClass: "transcodingProgress hide" }); + transcodingProgress.outerHTML = indicators.getProgressHtml(0, { + containerClass: "transcodingProgress hide" + }); } var imgUrl = DashboardPage.getNowPlayingImageUrl(nowPlayingItem) || ""; @@ -815,10 +844,13 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa view.addEventListener("viewdestroy", function () { var page = this; var userActivityLog = page.userActivityLog; + if (userActivityLog) { userActivityLog.destroy(); } + var serverActivityLog = page.serverActivityLog; + if (serverActivityLog) { serverActivityLog.destroy(); } diff --git a/src/controllers/device.js b/src/controllers/device.js index e704b964aa..cfe7efbe73 100644 --- a/src/controllers/device.js +++ b/src/controllers/device.js @@ -1,23 +1,25 @@ -define(["loading", "libraryMenu", "dom", "emby-input", "emby-button"], function(loading, libraryMenu, dom) { +define(["loading", "libraryMenu", "dom", "emby-input", "emby-button"], function (loading, libraryMenu, dom) { "use strict"; function load(page, device, deviceOptions) { - page.querySelector("#txtCustomName", page).value = deviceOptions.CustomName || "", page.querySelector(".reportedName", page).innerHTML = device.Name || "" + page.querySelector("#txtCustomName", page).value = deviceOptions.CustomName || ""; + page.querySelector(".reportedName", page).innerHTML = device.Name || ""; } function loadData() { var page = this; loading.show(); - var id = getParameterByName("id"), - promise1 = ApiClient.getJSON(ApiClient.getUrl("Devices/Info", { - Id: id - })), - promise2 = ApiClient.getJSON(ApiClient.getUrl("Devices/Options", { - Id: id - })); - Promise.all([promise1, promise2]).then(function(responses) { - load(page, responses[0], responses[1]), loading.hide() - }) + var id = getParameterByName("id"); + var promise1 = ApiClient.getJSON(ApiClient.getUrl("Devices/Info", { + Id: id + })); + var promise2 = ApiClient.getJSON(ApiClient.getUrl("Devices/Options", { + Id: id + })); + Promise.all([promise1, promise2]).then(function (responses) { + load(page, responses[0], responses[1]); + loading.hide(); + }); } function save(page) { @@ -31,14 +33,18 @@ define(["loading", "libraryMenu", "dom", "emby-input", "emby-button"], function( CustomName: page.querySelector("#txtCustomName").value }), contentType: "application/json" - }).then(Dashboard.processServerConfigurationUpdateResult) + }).then(Dashboard.processServerConfigurationUpdateResult); } function onSubmit(e) { var form = this; - return save(dom.parentWithClass(form, "page")), e.preventDefault(), !1 + save(dom.parentWithClass(form, "page")); + e.preventDefault(); + return false; } - return function(view, params) { - view.querySelector("form").addEventListener("submit", onSubmit), view.addEventListener("viewshow", loadData) - } -}); \ No newline at end of file + + return function (view, params) { + view.querySelector("form").addEventListener("submit", onSubmit); + view.addEventListener("viewshow", loadData); + }; +}); diff --git a/src/controllers/devices.js b/src/controllers/devices.js index 94d7eb70ea..36f2cf88a6 100644 --- a/src/controllers/devices.js +++ b/src/controllers/devices.js @@ -1,61 +1,73 @@ -define(["loading", "dom", "libraryMenu", "globalize", "scripts/imagehelper", "humanedate", "emby-button", "emby-itemscontainer", "cardStyle"], function(loading, dom, libraryMenu, globalize, imageHelper) { +define(["loading", "dom", "libraryMenu", "globalize", "scripts/imagehelper", "humanedate", "emby-button", "emby-itemscontainer", "cardStyle"], function (loading, dom, libraryMenu, globalize, imageHelper) { "use strict"; function canDelete(deviceId) { - return deviceId !== ApiClient.deviceId() + return deviceId !== ApiClient.deviceId(); } function deleteDevice(page, id) { var msg = globalize.translate("DeleteDeviceConfirmation"); - require(["confirm"], function(confirm) { + + require(["confirm"], function (confirm) { confirm({ text: msg, title: globalize.translate("HeaderDeleteDevice"), confirmText: globalize.translate("ButtonDelete"), primary: "delete" - }).then(function() { - loading.show(), ApiClient.ajax({ + }).then(function () { + loading.show(); + ApiClient.ajax({ type: "DELETE", url: ApiClient.getUrl("Devices", { Id: id }) - }).then(function() { - loadData(page) - }) - }) - }) + }).then(function () { + loadData(page); + }); + }); + }); } function showDeviceMenu(view, btn, deviceId) { var menuItems = []; - canEdit && menuItems.push({ - name: globalize.translate("Edit"), - id: "open", - ironIcon: "mode-edit" - }), canDelete(deviceId) && menuItems.push({ - name: globalize.translate("Delete"), - id: "delete", - ironIcon: "delete" - }), require(["actionsheet"], function(actionsheet) { + + if (canEdit) { + menuItems.push({ + name: globalize.translate("Edit"), + id: "open", + ironIcon: "mode-edit" + }); + } + + if (canDelete(deviceId)) { + menuItems.push({ + name: globalize.translate("Delete"), + id: "delete", + ironIcon: "delete" + }); + } + + require(["actionsheet"], function (actionsheet) { actionsheet.show({ items: menuItems, positionTo: btn, - callback: function(id) { + callback: function (id) { switch (id) { case "open": Dashboard.navigate("device.html?id=" + deviceId); break; + case "delete": - deleteDevice(view, deviceId) + deleteDevice(view, deviceId); } } - }) - }) + }); + }); } function load(page, devices) { var html = ""; - html += devices.map(function(device) { + html += devices.map(function (device) { var deviceHtml = ""; deviceHtml += "

"; deviceHtml += '
'; @@ -63,20 +75,24 @@ define(["loading", "dom", "libraryMenu", "globalize", "scripts/imagehelper", "hu deviceHtml += '
'; deviceHtml += ''; var iconUrl = imageHelper.getDeviceIcon(device.Name); + if (iconUrl) { deviceHtml += '
"; deviceHtml += "
"; } else { deviceHtml += 'tablet_android'; } + deviceHtml += "
"; deviceHtml += "
"; deviceHtml += '
'; + if (canEdit || canDelete(device.Id)) { deviceHtml += '
'; deviceHtml += ''; deviceHtml += "
"; } + deviceHtml += "
"; deviceHtml += device.Name; deviceHtml += "
"; @@ -84,10 +100,12 @@ define(["loading", "dom", "libraryMenu", "globalize", "scripts/imagehelper", "hu deviceHtml += device.AppName + " " + device.AppVersion; deviceHtml += "
"; deviceHtml += "
"; + if (device.LastUserName) { deviceHtml += device.LastUserName; deviceHtml += ", " + humaneDate(device.DateLastActivity); } + deviceHtml += " "; deviceHtml += "
"; deviceHtml += "
"; @@ -99,17 +117,24 @@ define(["loading", "dom", "libraryMenu", "globalize", "scripts/imagehelper", "hu } function loadData(page) { - loading.show(), ApiClient.getJSON(ApiClient.getUrl("Devices")).then(function(result) { - load(page, result.Items), loading.hide() - }) + loading.show(); + ApiClient.getJSON(ApiClient.getUrl("Devices")).then(function (result) { + load(page, result.Items); + loading.hide(); + }); } + var canEdit = ApiClient.isMinServerVersion("3.4.1.31"); - return function(view, params) { - view.querySelector(".devicesList").addEventListener("click", function(e) { + return function (view, params) { + view.querySelector(".devicesList").addEventListener("click", function (e) { var btnDeviceMenu = dom.parentWithClass(e.target, "btnDeviceMenu"); - btnDeviceMenu && showDeviceMenu(view, btnDeviceMenu, btnDeviceMenu.getAttribute("data-id")) - }), view.addEventListener("viewshow", function() { - loadData(this) - }) - } + + if (btnDeviceMenu) { + showDeviceMenu(view, btnDeviceMenu, btnDeviceMenu.getAttribute("data-id")); + } + }); + view.addEventListener("viewshow", function () { + loadData(this); + }); + }; }); diff --git a/src/controllers/dlnaprofile.js b/src/controllers/dlnaprofile.js index b4e320e6e4..e9239693d8 100644 --- a/src/controllers/dlnaprofile.js +++ b/src/controllers/dlnaprofile.js @@ -65,8 +65,8 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in profile.ContainerProfiles = profile.ContainerProfiles || []; profile.CodecProfiles = profile.CodecProfiles || []; profile.ResponseProfiles = profile.ResponseProfiles || []; - var usersHtml = "" + users.map(function (u__w) { - return '"; + var usersHtml = "" + users.map(function (u) { + return '"; }).join(""); $("#selectUser", page).html(usersHtml).val(profile.UserId || ""); renderSubProfiles(page, profile); @@ -74,12 +74,12 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in function renderIdentificationHeaders(page, headers) { var index = 0; - var html = '
' + headers.map(function (h__e) { + var html = '
' + headers.map(function (h) { var li = '
'; li += 'info'; li += '
'; - li += '

' + h__e.Name + ": " + (h__e.Value || "") + "

"; - li += '
' + (h__e.Match || "") + "
"; + li += '

' + h.Name + ": " + (h.Value || "") + "

"; + li += '
' + (h.Match || "") + "
"; li += "
"; li += ''; li += "
"; @@ -130,11 +130,11 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in } function renderXmlDocumentAttributes(page, attribute) { - var html = '
' + attribute.map(function (h__r) { + var html = '
' + attribute.map(function (h) { var li = '
'; li += 'info'; li += '
'; - li += '

' + h__r.Name + " = " + (h__r.Value || "") + "

"; + li += '

' + h.Name + " = " + (h.Value || "") + "

"; li += "
"; li += ''; return li += "
"; @@ -172,11 +172,11 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in function renderSubtitleProfiles(page, profiles) { var index = 0; - var html = '
' + profiles.map(function (h__t) { + var html = '
' + profiles.map(function (h) { var li = '
'; li += 'info'; li += '
'; - li += '

' + (h__t.Format || "") + "

"; + li += '

' + (h.Format || "") + "

"; li += "
"; li += ''; li += "
"; @@ -248,8 +248,8 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in html += '
    '; var currentType; - for (var i__y = 0, length = profiles.length; i__y < length; i__y++) { - var profile = profiles[i__y]; + for (var i = 0, length = profiles.length; i < length; i++) { + var profile = profiles[i]; if (profile.Type !== currentType) { html += '
  • ' + profile.Type + "
  • "; @@ -257,7 +257,7 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in } html += ""; } @@ -308,8 +308,8 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in html += '
      '; var currentType; - for (var i__u = 0, length = profiles.length; i__u < length; i__u++) { - var profile = profiles[i__u]; + for (var i = 0, length = profiles.length; i < length; i++) { + var profile = profiles[i]; if (profile.Type !== currentType) { html += '
    • ' + profile.Type + "
    • "; @@ -317,7 +317,7 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in } html += ""; } @@ -394,8 +394,8 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in html += '
        '; var currentType; - for (var i__i = 0, length = profiles.length; i__i < length; i__i++) { - var profile = profiles[i__i]; + for (var i = 0, length = profiles.length; i < length; i++) { + var profile = profiles[i]; if (profile.Type !== currentType) { html += '
      • ' + profile.Type + "
      • "; @@ -403,19 +403,19 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in } html += ""; } @@ -465,8 +465,8 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in html += '
          '; var currentType; - for (var i__p = 0, length = profiles.length; i__p < length; i__p++) { - var profile = profiles[i__p]; + for (var i = 0, length = profiles.length; i < length; i++) { + var profile = profiles[i]; var type = profile.Type.replace("VideoAudio", "Video Audio"); if (type !== currentType) { @@ -475,19 +475,19 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in } html += ""; } @@ -537,8 +537,8 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in html += '
            '; var currentType; - for (var i__s = 0, length = profiles.length; i__s < length; i__s++) { - var profile = profiles[i__s]; + for (var i = 0, length = profiles.length; i < length; i++) { + var profile = profiles[i]; if (profile.Type !== currentType) { html += '
          • ' + profile.Type + "
          • "; @@ -546,7 +546,7 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in } html += ""; } @@ -649,8 +649,8 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in profile.Name = $("#txtName", page).val(); profile.EnableAlbumArtInDidl = $("#chkEnableAlbumArtInDidl", page).checked(); profile.EnableSingleAlbumArtLimit = $("#chkEnableSingleImageLimit", page).checked(); - profile.SupportedMediaTypes = $(".chkMediaType:checked", page).get().map(function (c__f) { - return c__f.getAttribute("data-value"); + profile.SupportedMediaTypes = $(".chkMediaType:checked", page).get().map(function (c) { + return c.getAttribute("data-value"); }).join(","); profile.Identification = profile.Identification || {}; profile.FriendlyName = $("#txtInfoFriendlyName", page).val(); diff --git a/src/controllers/dlnaprofiles.js b/src/controllers/dlnaprofiles.js index 95350120c5..ae708bcd4e 100644 --- a/src/controllers/dlnaprofiles.js +++ b/src/controllers/dlnaprofiles.js @@ -1,48 +1,75 @@ -define(["jQuery", "globalize", "loading", "libraryMenu", "listViewStyle", "emby-button"], function($, globalize, loading, libraryMenu) { +define(["jQuery", "globalize", "loading", "libraryMenu", "listViewStyle", "emby-button"], function ($, globalize, loading, libraryMenu) { "use strict"; function loadProfiles(page) { - loading.show(), ApiClient.getJSON(ApiClient.getUrl("Dlna/ProfileInfos")).then(function(result) { - renderUserProfiles(page, result), renderSystemProfiles(page, result), loading.hide() - }) + loading.show(); + ApiClient.getJSON(ApiClient.getUrl("Dlna/ProfileInfos")).then(function (result) { + renderUserProfiles(page, result); + renderSystemProfiles(page, result); + loading.hide(); + }); } function renderUserProfiles(page, profiles) { - renderProfiles(page, page.querySelector(".customProfiles"), profiles.filter(function(p) { - return "User" == p.Type - })) + renderProfiles(page, page.querySelector(".customProfiles"), profiles.filter(function (p) { + return "User" == p.Type; + })); } function renderSystemProfiles(page, profiles) { - renderProfiles(page, page.querySelector(".systemProfiles"), profiles.filter(function(p) { - return "System" == p.Type - })) + renderProfiles(page, page.querySelector(".systemProfiles"), profiles.filter(function (p) { + return "System" == p.Type; + })); } function renderProfiles(page, element, profiles) { var html = ""; - profiles.length && (html += '
            '); + + if (profiles.length) { + html += '
            '; + } + for (var i = 0, length = profiles.length; i < length; i++) { var profile = profiles[i]; - html += '
            ', html += 'live_tv', html += '", "User" == profile.Type && (html += ''), html += "
            " + html += '
            '; + html += 'live_tv'; + html += '"; + + if ("User" == profile.Type) { + html += ''; + } + + html += "
            "; } - profiles.length && (html += "
            "), element.innerHTML = html, $(".btnDeleteProfile", element).on("click", function() { + + if (profiles.length) { + html += "
            "; + } + + element.innerHTML = html; + $(".btnDeleteProfile", element).on("click", function () { var id = this.getAttribute("data-profileid"); - deleteProfile(page, id) - }) + deleteProfile(page, id); + }); } function deleteProfile(page, id) { - require(["confirm"], function(confirm) { - confirm(globalize.translate("MessageConfirmProfileDeletion"), globalize.translate("HeaderConfirmProfileDeletion")).then(function() { - loading.show(), ApiClient.ajax({ + require(["confirm"], function (confirm) { + confirm(globalize.translate("MessageConfirmProfileDeletion"), globalize.translate("HeaderConfirmProfileDeletion")).then(function () { + loading.show(); + ApiClient.ajax({ type: "DELETE", url: ApiClient.getUrl("Dlna/Profiles/" + id) - }).then(function() { - loading.hide(), loadProfiles(page) - }) - }) - }) + }).then(function () { + loading.hide(); + loadProfiles(page); + }); + }); + }); } function getTabs() { @@ -52,10 +79,11 @@ define(["jQuery", "globalize", "loading", "libraryMenu", "listViewStyle", "emby- }, { href: "dlnaprofiles.html", name: globalize.translate("TabProfiles") - }] + }]; } - $(document).on("pageshow", "#dlnaProfilesPage", function() { - libraryMenu.setTabs("dlna", 1, getTabs), loadProfiles(this) - }) -}); \ No newline at end of file + $(document).on("pageshow", "#dlnaProfilesPage", function () { + libraryMenu.setTabs("dlna", 1, getTabs); + loadProfiles(this); + }); +}); diff --git a/src/controllers/dlnasettings.js b/src/controllers/dlnasettings.js index cc4693096a..fbb3af1205 100644 --- a/src/controllers/dlnasettings.js +++ b/src/controllers/dlnasettings.js @@ -1,20 +1,34 @@ -define(["jQuery", "loading", "libraryMenu", "fnchecked"], function($, loading, libraryMenu) { +define(["jQuery", "loading", "libraryMenu", "fnchecked"], function ($, loading, libraryMenu) { "use strict"; function loadPage(page, config, users) { - page.querySelector("#chkEnablePlayTo").checked = config.EnablePlayTo, page.querySelector("#chkEnableDlnaDebugLogging").checked = config.EnableDebugLog, $("#txtClientDiscoveryInterval", page).val(config.ClientDiscoveryIntervalSeconds), $("#chkEnableServer", page).checked(config.EnableServer), $("#chkBlastAliveMessages", page).checked(config.BlastAliveMessages), $("#txtBlastInterval", page).val(config.BlastAliveMessageIntervalSeconds); - var usersHtml = users.map(function(u) { - return '" + page.querySelector("#chkEnablePlayTo").checked = config.EnablePlayTo; + page.querySelector("#chkEnableDlnaDebugLogging").checked = config.EnableDebugLog; + $("#txtClientDiscoveryInterval", page).val(config.ClientDiscoveryIntervalSeconds); + $("#chkEnableServer", page).checked(config.EnableServer); + $("#chkBlastAliveMessages", page).checked(config.BlastAliveMessages); + $("#txtBlastInterval", page).val(config.BlastAliveMessageIntervalSeconds); + var usersHtml = users.map(function (u) { + return '"; }).join(""); - $("#selectUser", page).html(usersHtml).val(config.DefaultUserId || ""), loading.hide() + $("#selectUser", page).html(usersHtml).val(config.DefaultUserId || ""); + loading.hide(); } function onSubmit() { loading.show(); var form = this; - return ApiClient.getNamedConfiguration("dlna").then(function(config) { - config.EnablePlayTo = form.querySelector("#chkEnablePlayTo").checked, config.EnableDebugLog = form.querySelector("#chkEnableDlnaDebugLogging").checked, config.ClientDiscoveryIntervalSeconds = $("#txtClientDiscoveryInterval", form).val(), config.EnableServer = $("#chkEnableServer", form).checked(), config.BlastAliveMessages = $("#chkBlastAliveMessages", form).checked(), config.BlastAliveMessageIntervalSeconds = $("#txtBlastInterval", form).val(), config.DefaultUserId = $("#selectUser", form).val(), ApiClient.updateNamedConfiguration("dlna", config).then(Dashboard.processServerConfigurationUpdateResult) - }), !1 + ApiClient.getNamedConfiguration("dlna").then(function (config) { + config.EnablePlayTo = form.querySelector("#chkEnablePlayTo").checked; + config.EnableDebugLog = form.querySelector("#chkEnableDlnaDebugLogging").checked; + config.ClientDiscoveryIntervalSeconds = $("#txtClientDiscoveryInterval", form).val(); + config.EnableServer = $("#chkEnableServer", form).checked(); + config.BlastAliveMessages = $("#chkBlastAliveMessages", form).checked(); + config.BlastAliveMessageIntervalSeconds = $("#txtBlastInterval", form).val(); + config.DefaultUserId = $("#selectUser", form).val(); + ApiClient.updateNamedConfiguration("dlna", config).then(Dashboard.processServerConfigurationUpdateResult); + }); + return false; } function getTabs() { @@ -24,17 +38,19 @@ define(["jQuery", "loading", "libraryMenu", "fnchecked"], function($, loading, l }, { href: "dlnaprofiles.html", name: Globalize.translate("TabProfiles") - }] + }]; } - $(document).on("pageinit", "#dlnaSettingsPage", function() { - $(".dlnaSettingsForm").off("submit", onSubmit).on("submit", onSubmit) - }).on("pageshow", "#dlnaSettingsPage", function() { - libraryMenu.setTabs("dlna", 0, getTabs), loading.show(); - var page = this, - promise1 = ApiClient.getNamedConfiguration("dlna"), - promise2 = ApiClient.getUsers(); - Promise.all([promise1, promise2]).then(function(responses) { - loadPage(page, responses[0], responses[1]) - }) - }) -}); \ No newline at end of file + + $(document).on("pageinit", "#dlnaSettingsPage", function () { + $(".dlnaSettingsForm").off("submit", onSubmit).on("submit", onSubmit); + }).on("pageshow", "#dlnaSettingsPage", function () { + libraryMenu.setTabs("dlna", 0, getTabs); + loading.show(); + var page = this; + var promise1 = ApiClient.getNamedConfiguration("dlna"); + var promise2 = ApiClient.getUsers(); + Promise.all([promise1, promise2]).then(function (responses) { + loadPage(page, responses[0], responses[1]); + }); + }); +}); diff --git a/src/controllers/edititemmetadata.js b/src/controllers/edititemmetadata.js index bb5e70695a..aba741d64c 100644 --- a/src/controllers/edititemmetadata.js +++ b/src/controllers/edititemmetadata.js @@ -1,17 +1,31 @@ -define(["loading", "scripts/editorsidebar"], function(loading) { +define(["loading", "scripts/editorsidebar"], function (loading) { "use strict"; function reload(context, itemId) { - loading.show(), itemId ? require(["metadataEditor"], function(metadataEditor) { - metadataEditor.embed(context.querySelector(".editPageInnerContent"), itemId, ApiClient.serverInfo().Id) - }) : (context.querySelector(".editPageInnerContent").innerHTML = "", loading.hide()) + loading.show(); + + if (itemId) { + require(["metadataEditor"], function (metadataEditor) { + metadataEditor.embed(context.querySelector(".editPageInnerContent"), itemId, ApiClient.serverInfo().Id); + }); + } else { + context.querySelector(".editPageInnerContent").innerHTML = ""; + loading.hide(); + } } - return function(view, params) { - view.addEventListener("viewshow", function() { - reload(this, MetadataEditor.getCurrentItemId()) - }), MetadataEditor.setCurrentItemId(null), view.querySelector(".libraryTree").addEventListener("itemclicked", function(event) { + + return function (view, params) { + view.addEventListener("viewshow", function () { + reload(this, MetadataEditor.getCurrentItemId()); + }); + MetadataEditor.setCurrentItemId(null); + view.querySelector(".libraryTree").addEventListener("itemclicked", function (event) { var data = event.detail; - data.id != MetadataEditor.getCurrentItemId() && (MetadataEditor.setCurrentItemId(data.id), reload(view, data.id)) - }) - } -}); \ No newline at end of file + + if (data.id != MetadataEditor.getCurrentItemId()) { + MetadataEditor.setCurrentItemId(data.id); + reload(view, data.id); + } + }); + }; +}); diff --git a/src/controllers/encodingsettings.js b/src/controllers/encodingsettings.js index 0319d59a79..f3dfd2706e 100644 --- a/src/controllers/encodingsettings.js +++ b/src/controllers/encodingsettings.js @@ -1,9 +1,9 @@ -define(["jQuery", "loading", "globalize", "dom", "libraryMenu"], function($, loading, globalize, dom, libraryMenu) { +define(["jQuery", "loading", "globalize", "dom", "libraryMenu"], function ($, loading, globalize, dom, libraryMenu) { "use strict"; function loadPage(page, config, systemInfo) { - Array.prototype.forEach.call(page.querySelectorAll(".chkDecodeCodec"), function(c) { - c.checked = -1 !== (config.HardwareDecodingCodecs || []).indexOf(c.getAttribute("data-codec")) + Array.prototype.forEach.call(page.querySelectorAll(".chkDecodeCodec"), function (c) { + c.checked = -1 !== (config.HardwareDecodingCodecs || []).indexOf(c.getAttribute("data-codec")); }); page.querySelector("#chkHardwareEncoding").checked = config.EnableHardwareEncoding; $("#selectVideoDecoder", page).val(config.HardwareAccelerationType); @@ -17,19 +17,22 @@ define(["jQuery", "loading", "globalize", "dom", "libraryMenu"], function($, loa page.querySelector("#chkEnableSubtitleExtraction").checked = config.EnableSubtitleExtraction || false; page.querySelector("#selectVideoDecoder").dispatchEvent(new CustomEvent("change", { bubbles: true - })), loading.hide() + })); + loading.hide(); } function onSaveEncodingPathFailure(response) { loading.hide(); var msg = ""; - msg = globalize.translate("FFmpegSavePathNotFound"), require(["alert"], function(alert) { - alert(msg) - }) + msg = globalize.translate("FFmpegSavePathNotFound"); + + require(["alert"], function (alert) { + alert(msg); + }); } function updateEncoder(form) { - return ApiClient.getSystemInfo().then(function(systemInfo) { + return ApiClient.getSystemInfo().then(function (systemInfo) { return ApiClient.ajax({ url: ApiClient.getUrl("System/MediaEncoder/Path"), type: "POST", @@ -37,37 +40,67 @@ define(["jQuery", "loading", "globalize", "dom", "libraryMenu"], function($, loa Path: form.querySelector(".txtEncoderPath").value, PathType: "Custom" } - }).then(Dashboard.processServerConfigurationUpdateResult, onSaveEncodingPathFailure) - }) + }).then(Dashboard.processServerConfigurationUpdateResult, onSaveEncodingPathFailure); + }); } function onSubmit() { - var form = this, - onDecoderConfirmed = function() { - loading.show(), ApiClient.getNamedConfiguration("encoding").then(function(config) { - config.DownMixAudioBoost = $("#txtDownMixAudioBoost", form).val(), config.TranscodingTempPath = $("#txtTranscodingTempPath", form).val(), config.EncodingThreadCount = $("#selectThreadCount", form).val(), config.HardwareAccelerationType = $("#selectVideoDecoder", form).val(), config.VaapiDevice = $("#txtVaapiDevice", form).val(), config.H264Preset = form.querySelector("#selectH264Preset").value, config.H264Crf = parseInt(form.querySelector("#txtH264Crf").value || "0"), config.EnableSubtitleExtraction = form.querySelector("#chkEnableSubtitleExtraction").checked, config.HardwareDecodingCodecs = Array.prototype.map.call(Array.prototype.filter.call(form.querySelectorAll(".chkDecodeCodec"), function(c) { - return c.checked - }), function(c) { - return c.getAttribute("data-codec") - }), config.EnableHardwareEncoding = form.querySelector("#chkHardwareEncoding").checked, ApiClient.updateNamedConfiguration("encoding", config).then(function() { - updateEncoder(form) - }) - }) - }; - return $("#selectVideoDecoder", form).val() ? require(["alert"], function(alert) { - alert({ - title: globalize.translate("TitleHardwareAcceleration"), - text: globalize.translate("HardwareAccelerationWarning") - }).then(onDecoderConfirmed) - }) : onDecoderConfirmed(), !1 + var form = this; + + var onDecoderConfirmed = function () { + loading.show(); + ApiClient.getNamedConfiguration("encoding").then(function (config) { + config.DownMixAudioBoost = $("#txtDownMixAudioBoost", form).val(); + config.TranscodingTempPath = $("#txtTranscodingTempPath", form).val(); + config.EncodingThreadCount = $("#selectThreadCount", form).val(); + config.HardwareAccelerationType = $("#selectVideoDecoder", form).val(); + config.VaapiDevice = $("#txtVaapiDevice", form).val(); + config.H264Preset = form.querySelector("#selectH264Preset").value; + config.H264Crf = parseInt(form.querySelector("#txtH264Crf").value || "0"); + config.EnableSubtitleExtraction = form.querySelector("#chkEnableSubtitleExtraction").checked; + config.HardwareDecodingCodecs = Array.prototype.map.call(Array.prototype.filter.call(form.querySelectorAll(".chkDecodeCodec"), function (c) { + return c.checked; + }), function (c) { + return c.getAttribute("data-codec"); + }); + config.EnableHardwareEncoding = form.querySelector("#chkHardwareEncoding").checked; + ApiClient.updateNamedConfiguration("encoding", config).then(function () { + updateEncoder(form); + }); + }); + }; + + if ($("#selectVideoDecoder", form).val()) { + require(["alert"], function (alert) { + alert({ + title: globalize.translate("TitleHardwareAcceleration"), + text: globalize.translate("HardwareAccelerationWarning") + }).then(onDecoderConfirmed); + }); + } else { + onDecoderConfirmed(); + } + + return false; } function setDecodingCodecsVisible(context, value) { value = value || ""; var any; - Array.prototype.forEach.call(context.querySelectorAll(".chkDecodeCodec"), function(c) { - -1 === c.getAttribute("data-types").split(",").indexOf(value) ? dom.parentWithTag(c, "LABEL").classList.add("hide") : (dom.parentWithTag(c, "LABEL").classList.remove("hide"), any = !0) - }), any ? context.querySelector(".decodingCodecsList").classList.remove("hide") : context.querySelector(".decodingCodecsList").classList.add("hide") + Array.prototype.forEach.call(context.querySelectorAll(".chkDecodeCodec"), function (c) { + if (-1 === c.getAttribute("data-types").split(",").indexOf(value)) { + dom.parentWithTag(c, "LABEL").classList.add("hide"); + } else { + dom.parentWithTag(c, "LABEL").classList.remove("hide"); + any = true; + } + }); + + if (any) { + context.querySelector(".decodingCodecsList").classList.remove("hide"); + } else { + context.querySelector(".decodingCodecsList").classList.add("hide"); + } } function getTabs() { @@ -80,44 +113,69 @@ define(["jQuery", "loading", "globalize", "dom", "libraryMenu"], function($, loa }, { href: "streamingsettings.html", name: Globalize.translate("TabStreaming") - }] + }]; } - $(document).on("pageinit", "#encodingSettingsPage", function() { + $(document).on("pageinit", "#encodingSettingsPage", function () { var page = this; - page.querySelector("#selectVideoDecoder").addEventListener("change", function() { - "vaapi" == this.value ? (page.querySelector(".fldVaapiDevice").classList.remove("hide"), page.querySelector("#txtVaapiDevice").setAttribute("required", "required")) : (page.querySelector(".fldVaapiDevice").classList.add("hide"), page.querySelector("#txtVaapiDevice").removeAttribute("required")), this.value ? page.querySelector(".hardwareAccelerationOptions").classList.remove("hide") : page.querySelector(".hardwareAccelerationOptions").classList.add("hide"), setDecodingCodecsVisible(page, this.value) - }), $("#btnSelectEncoderPath", page).on("click.selectDirectory", function() { - require(["directorybrowser"], function(directoryBrowser) { - var picker = new directoryBrowser; + page.querySelector("#selectVideoDecoder").addEventListener("change", function () { + if ("vaapi" == this.value) { + page.querySelector(".fldVaapiDevice").classList.remove("hide"); + page.querySelector("#txtVaapiDevice").setAttribute("required", "required"); + } else { + page.querySelector(".fldVaapiDevice").classList.add("hide"); + page.querySelector("#txtVaapiDevice").removeAttribute("required"); + } + + if (this.value) { + page.querySelector(".hardwareAccelerationOptions").classList.remove("hide"); + } else { + page.querySelector(".hardwareAccelerationOptions").classList.add("hide"); + } + + setDecodingCodecsVisible(page, this.value); + }); + $("#btnSelectEncoderPath", page).on("click.selectDirectory", function () { + require(["directorybrowser"], function (directoryBrowser) { + var picker = new directoryBrowser(); picker.show({ - includeFiles: !0, - callback: function(path) { - path && $(".txtEncoderPath", page).val(path), picker.close() + includeFiles: true, + callback: function (path) { + if (path) { + $(".txtEncoderPath", page).val(path); + } + + picker.close(); } - }) - }) - }), $("#btnSelectTranscodingTempPath", page).on("click.selectDirectory", function() { - require(["directorybrowser"], function(directoryBrowser) { - var picker = new directoryBrowser; + }); + }); + }); + $("#btnSelectTranscodingTempPath", page).on("click.selectDirectory", function () { + require(["directorybrowser"], function (directoryBrowser) { + var picker = new directoryBrowser(); picker.show({ - callback: function(path) { - path && $("#txtTranscodingTempPath", page).val(path), picker.close() + callback: function (path) { + if (path) { + $("#txtTranscodingTempPath", page).val(path); + } + + picker.close(); }, - validateWriteable: !0, + validateWriteable: true, header: globalize.translate("HeaderSelectTranscodingPath"), instruction: globalize.translate("HeaderSelectTranscodingPathHelp") - }) - }) - }), $(".encodingSettingsForm").off("submit", onSubmit).on("submit", onSubmit) - }).on("pageshow", "#encodingSettingsPage", function() { + }); + }); + }); + $(".encodingSettingsForm").off("submit", onSubmit).on("submit", onSubmit); + }).on("pageshow", "#encodingSettingsPage", function () { loading.show(); libraryMenu.setTabs("playback", 0, getTabs); var page = this; - ApiClient.getNamedConfiguration("encoding").then(function(config) { - ApiClient.getSystemInfo().then(function(systemInfo) { + ApiClient.getNamedConfiguration("encoding").then(function (config) { + ApiClient.getSystemInfo().then(function (systemInfo) { loadPage(page, config, systemInfo); - }) - }) - }) + }); + }); + }); }); diff --git a/src/controllers/forgotpassword.js b/src/controllers/forgotpassword.js index ac010a9b34..e0f8ea4ef8 100644 --- a/src/controllers/forgotpassword.js +++ b/src/controllers/forgotpassword.js @@ -1,37 +1,53 @@ -define([], function() { +define([], function () { "use strict"; function processForgotPasswordResult(result) { - if ("ContactAdmin" == result.Action) return void Dashboard.alert({ - message: Globalize.translate("MessageContactAdminToResetPassword"), - title: Globalize.translate("HeaderForgotPassword") - }); - if ("InNetworkRequired" == result.Action) return void Dashboard.alert({ - message: Globalize.translate("MessageForgotPasswordInNetworkRequired"), - title: Globalize.translate("HeaderForgotPassword") - }); + if ("ContactAdmin" == result.Action) { + return void Dashboard.alert({ + message: Globalize.translate("MessageContactAdminToResetPassword"), + title: Globalize.translate("HeaderForgotPassword") + }); + } + + if ("InNetworkRequired" == result.Action) { + return void Dashboard.alert({ + message: Globalize.translate("MessageForgotPasswordInNetworkRequired"), + title: Globalize.translate("HeaderForgotPassword") + }); + } + if ("PinCode" == result.Action) { var msg = Globalize.translate("MessageForgotPasswordFileCreated"); - return msg += "
            ", msg += "
            ", msg += "Enter PIN here to finish Password Reset
            " ,msg += "
            ",msg += result.PinFile, msg += "
            ", void Dashboard.alert({ + msg += "
            "; + msg += "
            "; + msg += "Enter PIN here to finish Password Reset
            "; + msg += "
            "; + msg += result.PinFile; + msg += "
            "; + return void Dashboard.alert({ message: msg, title: Globalize.translate("HeaderForgotPassword"), - callback: function() { - Dashboard.navigate("forgotpasswordpin.html") + callback: function () { + Dashboard.navigate("forgotpasswordpin.html"); } - }) + }); } } - return function(view, params) { + + return function (view, params) { function onSubmit(e) { - return ApiClient.ajax({ + ApiClient.ajax({ type: "POST", url: ApiClient.getUrl("Users/ForgotPassword"), dataType: "json", data: { EnteredUsername: view.querySelector("#txtName").value } - }).then(processForgotPasswordResult), e.preventDefault(), !1 + }).then(processForgotPasswordResult); + e.preventDefault(); + return false; } - view.querySelector("form").addEventListener("submit", onSubmit) - } + + view.querySelector("form").addEventListener("submit", onSubmit); + }; }); diff --git a/src/controllers/forgotpasswordpin.js b/src/controllers/forgotpasswordpin.js index e7dccc7be1..47b1c899b9 100644 --- a/src/controllers/forgotpasswordpin.js +++ b/src/controllers/forgotpasswordpin.js @@ -1,33 +1,41 @@ -define([], function() { +define([], function () { "use strict"; function processForgotPasswordResult(result) { if (result.Success) { var msg = Globalize.translate("MessagePasswordResetForUsers"); - return msg += "
            ", msg += "
            ", msg += result.UsersReset.join("
            "), void Dashboard.alert({ + msg += "
            "; + msg += "
            "; + msg += result.UsersReset.join("
            "); + return void Dashboard.alert({ message: msg, title: Globalize.translate("HeaderPasswordReset"), - callback: function() { - window.location.href = "index.html" + callback: function () { + window.location.href = "index.html"; } - }) + }); } + Dashboard.alert({ message: Globalize.translate("MessageInvalidForgotPasswordPin"), title: Globalize.translate("HeaderPasswordReset") - }) + }); } - return function(view, params) { + + return function (view, params) { function onSubmit(e) { - return ApiClient.ajax({ + ApiClient.ajax({ type: "POST", url: ApiClient.getUrl("Users/ForgotPassword/Pin"), dataType: "json", data: { Pin: view.querySelector("#txtPin").value } - }).then(processForgotPasswordResult), e.preventDefault(), !1 + }).then(processForgotPasswordResult); + e.preventDefault(); + return false; } - view.querySelector("form").addEventListener("submit", onSubmit) - } -}); \ No newline at end of file + + view.querySelector("form").addEventListener("submit", onSubmit); + }; +}); diff --git a/src/controllers/home.js b/src/controllers/home.js index 0ab31f291d..b1dd70ebd6 100644 --- a/src/controllers/home.js +++ b/src/controllers/home.js @@ -1,4 +1,4 @@ -define(["tabbedView", "globalize", "require", "emby-tabs", "emby-button", "emby-scroller"], function(TabbedView, globalize, require) { +define(["tabbedView", "globalize", "require", "emby-tabs", "emby-button", "emby-scroller"], function (TabbedView, globalize, require) { "use strict"; function getTabs() { @@ -6,47 +6,70 @@ define(["tabbedView", "globalize", "require", "emby-tabs", "emby-button", "emby- name: globalize.translate("Home") }, { name: globalize.translate("Favorites") - }] + }]; } function getDefaultTabIndex() { - return 0 + return 0; } function getRequirePromise(deps) { - return new Promise(function(resolve, reject) { - require(deps, resolve) - }) + return new Promise(function (resolve, reject) { + require(deps, resolve); + }); } function getTabController(index) { - if (null == index) throw new Error("index cannot be null"); + if (null == index) { + throw new Error("index cannot be null"); + } + var depends = []; + switch (index) { case 0: depends.push("controllers/hometab"); break; + case 1: - depends.push("controllers/favorites") + depends.push("controllers/favorites"); } + var instance = this; - return getRequirePromise(depends).then(function(controllerFactory) { + return getRequirePromise(depends).then(function (controllerFactory) { var controller = instance.tabControllers[index]; + if (!controller) { - controller = new controllerFactory(instance.view.querySelector(".tabContent[data-index='" + index + "']"), instance.params), instance.tabControllers[index] = controller + controller = new controllerFactory(instance.view.querySelector(".tabContent[data-index='" + index + "']"), instance.params); + instance.tabControllers[index] = controller; } - return controller - }) + + return controller; + }); } function HomeView(view, params) { - TabbedView.call(this, view, params) + TabbedView.call(this, view, params); } - return Object.assign(HomeView.prototype, TabbedView.prototype), HomeView.prototype.getTabs = getTabs, HomeView.prototype.getDefaultTabIndex = getDefaultTabIndex, HomeView.prototype.getTabController = getTabController, HomeView.prototype.setTitle = function() { - Emby.Page.setTitle(null) - }, HomeView.prototype.onPause = function() { - TabbedView.prototype.onPause.call(this), document.querySelector(".skinHeader").classList.remove("noHomeButtonHeader") - }, HomeView.prototype.onResume = function(options) { - TabbedView.prototype.onResume.call(this, options), document.querySelector(".skinHeader").classList.add("noHomeButtonHeader") - }, HomeView -}); \ No newline at end of file + + Object.assign(HomeView.prototype, TabbedView.prototype); + HomeView.prototype.getTabs = getTabs; + HomeView.prototype.getDefaultTabIndex = getDefaultTabIndex; + HomeView.prototype.getTabController = getTabController; + + HomeView.prototype.setTitle = function () { + Emby.Page.setTitle(null); + }; + + HomeView.prototype.onPause = function () { + TabbedView.prototype.onPause.call(this); + document.querySelector(".skinHeader").classList.remove("noHomeButtonHeader"); + }; + + HomeView.prototype.onResume = function (options) { + TabbedView.prototype.onResume.call(this, options); + document.querySelector(".skinHeader").classList.add("noHomeButtonHeader"); + }; + + return HomeView; +}); diff --git a/src/controllers/hometab.js b/src/controllers/hometab.js index fed9b72146..d2adcb2da2 100644 --- a/src/controllers/hometab.js +++ b/src/controllers/hometab.js @@ -1,35 +1,74 @@ -define(["userSettings", "loading", "connectionManager", "apphost", "layoutManager", "focusManager", "homeSections", "emby-itemscontainer"], function(userSettings, loading, connectionManager, appHost, layoutManager, focusManager, homeSections) { +define(["userSettings", "loading", "connectionManager", "apphost", "layoutManager", "focusManager", "homeSections", "emby-itemscontainer"], function (userSettings, loading, connectionManager, appHost, layoutManager, focusManager, homeSections) { "use strict"; function HomeTab(view, params) { - this.view = view, this.params = params, this.apiClient = connectionManager.currentApiClient(), this.sectionsContainer = view.querySelector(".sections"), view.querySelector(".sections").addEventListener("settingschange", onHomeScreenSettingsChanged.bind(this)) + this.view = view; + this.params = params; + this.apiClient = connectionManager.currentApiClient(); + this.sectionsContainer = view.querySelector(".sections"); + view.querySelector(".sections").addEventListener("settingschange", onHomeScreenSettingsChanged.bind(this)); } function onHomeScreenSettingsChanged() { - this.sectionsRendered = !1, this.paused || this.onResume({ - refresh: !0 - }) + this.sectionsRendered = false; + + if (!this.paused) { + this.onResume({ + refresh: true + }); + } } - return HomeTab.prototype.onResume = function(options) { + + HomeTab.prototype.onResume = function (options) { if (this.sectionsRendered) { var sectionsContainer = this.sectionsContainer; - return sectionsContainer ? homeSections.resume(sectionsContainer, options) : Promise.resolve() + + if (sectionsContainer) { + return homeSections.resume(sectionsContainer, options); + } + + return Promise.resolve(); } + loading.show(); - var view = this.view, - apiClient = this.apiClient; - return this.destroyHomeSections(), this.sectionsRendered = !0, apiClient.getCurrentUser().then(function(user) { - return homeSections.loadSections(view.querySelector(".sections"), apiClient, user, userSettings).then(function() { - options.autoFocus && focusManager.autoFocus(view), loading.hide() - }) - }) - }, HomeTab.prototype.onPause = function() { + var view = this.view; + var apiClient = this.apiClient; + this.destroyHomeSections(); + this.sectionsRendered = true; + return apiClient.getCurrentUser().then(function (user) { + return homeSections.loadSections(view.querySelector(".sections"), apiClient, user, userSettings).then(function () { + if (options.autoFocus) { + focusManager.autoFocus(view); + } + + loading.hide(); + }); + }); + }; + + HomeTab.prototype.onPause = function () { var sectionsContainer = this.sectionsContainer; - sectionsContainer && homeSections.pause(sectionsContainer) - }, HomeTab.prototype.destroy = function() { - this.view = null, this.params = null, this.apiClient = null, this.destroyHomeSections(), this.sectionsContainer = null - }, HomeTab.prototype.destroyHomeSections = function() { + + if (sectionsContainer) { + homeSections.pause(sectionsContainer); + } + }; + + HomeTab.prototype.destroy = function () { + this.view = null; + this.params = null; + this.apiClient = null; + this.destroyHomeSections(); + this.sectionsContainer = null; + }; + + HomeTab.prototype.destroyHomeSections = function () { var sectionsContainer = this.sectionsContainer; - sectionsContainer && homeSections.destroySections(sectionsContainer) - }, HomeTab -}); \ No newline at end of file + + if (sectionsContainer) { + homeSections.destroySections(sectionsContainer); + } + }; + + return HomeTab; +}); diff --git a/src/controllers/installedplugins.js b/src/controllers/installedplugins.js index f9653fe260..a88f49d186 100644 --- a/src/controllers/installedplugins.js +++ b/src/controllers/installedplugins.js @@ -1,21 +1,22 @@ -define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button"], function(loading, libraryMenu, dom, globalize) { +define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button"], function (loading, libraryMenu, dom, globalize) { "use strict"; function deletePlugin(page, uniqueid, name) { var msg = globalize.translate("UninstallPluginConfirmation").replace("{0}", name); - require(["confirm"], function(confirm) { + + require(["confirm"], function (confirm) { confirm({ title: globalize.translate("UninstallPluginHeader"), text: msg, primary: "delete", confirmText: globalize.translate("UninstallPluginHeader") - }).then(function() { + }).then(function () { loading.show(); - ApiClient.uninstallPlugin(uniqueid).then(function() { + ApiClient.uninstallPlugin(uniqueid).then(function () { reloadList(page); }); - }) - }) + }); + }); } function showNoConfigurationMessage() { @@ -31,23 +32,24 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button" } function getPluginCardHtml(plugin, pluginConfigurationPages) { - var configPage = pluginConfigurationPages.filter(function(pluginConfigurationPage) { - return pluginConfigurationPage.PluginId == plugin.Id; + var configPage = pluginConfigurationPages.filter(function (pluginConfigurationPage) { + return pluginConfigurationPage.PluginId == plugin.Id; })[0]; var configPageUrl = configPage ? Dashboard.getConfigurationPageUrl(configPage.Name) : null; - var html = ""; html += "
            "; html += '
            '; html += '"; html += '
            '; @@ -67,21 +69,26 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button" } function renderPlugins(page, plugins) { - ApiClient.getJSON(ApiClient.getUrl("web/configurationpages") + "?pageType=PluginConfiguration").then(function(configPages) { + ApiClient.getJSON(ApiClient.getUrl("web/configurationpages") + "?pageType=PluginConfiguration").then(function (configPages) { populateList(page, plugins, configPages); }); } function populateList(page, plugins, pluginConfigurationPages) { - plugins = plugins.sort(function(plugin1, plugin2) { - return plugin1.Name > plugin2.Name ? 1 : -1 + plugins = plugins.sort(function (plugin1, plugin2) { + if (plugin1.Name > plugin2.Name) { + return 1; + } + + return -1; }); - var html = plugins.map(function(p) { - return getPluginCardHtml(p, pluginConfigurationPages) + var html = plugins.map(function (p) { + return getPluginCardHtml(p, pluginConfigurationPages); }).join(""); var installedPluginsElement = page.querySelector(".installedPlugins"); installedPluginsElement.removeEventListener("click", onInstalledPluginsClick); installedPluginsElement.addEventListener("click", onInstalledPluginsClick); + if (plugins.length) { installedPluginsElement.classList.add("itemsContainer"); installedPluginsElement.classList.add("vertical-wrap"); @@ -93,6 +100,7 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button" html += "

            "; html += "
            "; } + installedPluginsElement.innerHTML = html; loading.hide(); } @@ -103,6 +111,7 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button" var name = card.getAttribute("data-name"); var configHref = card.querySelector(".cardContent").getAttribute("href"); var menuItems = []; + if (configHref) { menuItems.push({ name: globalize.translate("ButtonSettings"), @@ -110,22 +119,25 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button" ironIcon: "mode-edit" }); } + menuItems.push({ name: globalize.translate("ButtonUninstall"), id: "delete", ironIcon: "delete" }); - require(["actionsheet"], function(actionsheet) { + + require(["actionsheet"], function (actionsheet) { actionsheet.show({ items: menuItems, positionTo: elem, - callback: function(resultId) { + callback: function (resultId) { switch (resultId) { case "open": Dashboard.navigate(configHref); break; + case "delete": - deletePlugin(page, id, name) + deletePlugin(page, id, name); } } }); @@ -134,7 +146,7 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button" function reloadList(page) { loading.show(); - ApiClient.getInstalledPlugins().then(function(plugins) { + ApiClient.getInstalledPlugins().then(function (plugins) { renderPlugins(page, plugins); }); } @@ -146,7 +158,7 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button" }, { href: "availableplugins.html", name: globalize.translate("TabCatalog") - }] + }]; } function onInstalledPluginsClick(e) { @@ -156,16 +168,18 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button" showConnectMessage(); } else { var btnCardMenu = dom.parentWithClass(e.target, "btnCardMenu"); - btnCardMenu && showPluginMenu(dom.parentWithClass(btnCardMenu, "page"), btnCardMenu); + + if (btnCardMenu) { + showPluginMenu(dom.parentWithClass(btnCardMenu, "page"), btnCardMenu); + } } } - pageIdOn("pageshow", "pluginsPage", function() { + pageIdOn("pageshow", "pluginsPage", function () { libraryMenu.setTabs("plugins", 0, getTabs); reloadList(this); }); - window.PluginsPage = { renderPlugins: renderPlugins - } + }; }); diff --git a/src/controllers/itemdetailpage.js b/src/controllers/itemdetailpage.js index 03e0f68a9b..5bc54edf74 100644 --- a/src/controllers/itemdetailpage.js +++ b/src/controllers/itemdetailpage.js @@ -1,37 +1,61 @@ -define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuilder", "datetime", "mediaInfo", "backdrop", "listView", "itemContextMenu", "itemHelper", "dom", "indicators", "apphost", "imageLoader", "libraryMenu", "globalize", "browser", "events", "scrollHelper", "playbackManager", "libraryBrowser", "scrollStyles", "emby-itemscontainer", "emby-checkbox", "emby-button", "emby-playstatebutton", "emby-ratingbutton", "emby-scroller", "emby-select"], function(loading, appRouter, layoutManager, connectionManager, cardBuilder, datetime, mediaInfo, backdrop, listView, itemContextMenu, itemHelper, dom, indicators, appHost, imageLoader, libraryMenu, globalize, browser, events, scrollHelper, playbackManager, libraryBrowser) { +define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuilder", "datetime", "mediaInfo", "backdrop", "listView", "itemContextMenu", "itemHelper", "dom", "indicators", "apphost", "imageLoader", "libraryMenu", "globalize", "browser", "events", "scrollHelper", "playbackManager", "libraryBrowser", "scrollStyles", "emby-itemscontainer", "emby-checkbox", "emby-button", "emby-playstatebutton", "emby-ratingbutton", "emby-scroller", "emby-select"], function (loading, appRouter, layoutManager, connectionManager, cardBuilder, datetime, mediaInfo, backdrop, listView, itemContextMenu, itemHelper, dom, indicators, appHost, imageLoader, libraryMenu, globalize, browser, events, scrollHelper, playbackManager, libraryBrowser) { "use strict"; function getPromise(apiClient, params) { var id = params.id; - if (id) return apiClient.getItem(apiClient.getCurrentUserId(), id); - if (params.seriesTimerId) return apiClient.getLiveTvSeriesTimer(params.seriesTimerId); - var name = params.genre; - if (name) return apiClient.getGenre(name, apiClient.getCurrentUserId()); - if (name = params.musicgenre) return apiClient.getMusicGenre(name, apiClient.getCurrentUserId()); - if (name = params.musicartist) return apiClient.getArtist(name, apiClient.getCurrentUserId()); - throw new Error("Invalid request") + + if (id) { + return apiClient.getItem(apiClient.getCurrentUserId(), id); + } + + if (params.seriesTimerId) { + return apiClient.getLiveTvSeriesTimer(params.seriesTimerId); + } + + if (params.genre) { + return apiClient.getGenre(params.genre, apiClient.getCurrentUserId()); + } + + if (params.musicgenre) { + return apiClient.getMusicGenre(params.musicgenre, apiClient.getCurrentUserId()); + } + + if (params.musicartist) { + return apiClient.getArtist(params.musicartist, apiClient.getCurrentUserId()); + } + + throw new Error("Invalid request"); } function hideAll(page, className, show) { - var i, length, elems = page.querySelectorAll("." + className); - for (i = 0, length = elems.length; i < length; i++) show ? elems[i].classList.remove("hide") : elems[i].classList.add("hide") + var i; + var length; + var elems = page.querySelectorAll("." + className); + + for (i = 0, length = elems.length; i < length; i++) { + if (show) { + elems[i].classList.remove("hide"); + } else { + elems[i].classList.add("hide"); + } + } } function getContextMenuOptions(item, user, button) { var options = { item: item, - open: !1, - play: !1, - playAllFromHere: !1, - queueAllFromHere: !1, + open: false, + play: false, + playAllFromHere: false, + queueAllFromHere: false, positionTo: button, - cancelTimer: !1, - record: !1, - deleteItem: !0 === item.IsFolder, - shuffle: !1, - instantMix: !1, + cancelTimer: false, + record: false, + deleteItem: true === item.IsFolder, + shuffle: false, + instantMix: false, user: user, - share: !0 + share: true }; return options; } @@ -39,18 +63,20 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild function getProgramScheduleHtml(items, options) { options = options || {}; var html = ""; - return html += '
            ', html += listView.getListViewHtml({ + html += '
            '; + html += listView.getListViewHtml({ items: items, - enableUserDataButtons: !1, - image: !0, + enableUserDataButtons: false, + image: true, imageSource: "channel", - showProgramDateTime: !0, - showChannel: !1, - mediaInfo: !1, + showProgramDateTime: true, + showChannel: false, + mediaInfo: false, action: "none", - moreButton: !1, - recordButton: !1 - }), html += "
            " + moreButton: false, + recordButton: false + }); + return html += "
            "; } function renderSeriesTimerSchedule(page, apiClient, seriesTimerId) { @@ -59,184 +85,339 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild ImageTypeLimit: 1, EnableImageTypes: "Primary,Backdrop,Thumb", SortBy: "StartDate", - EnableTotalRecordCount: !1, - EnableUserData: !1, + EnableTotalRecordCount: false, + EnableUserData: false, SeriesTimerId: seriesTimerId, Fields: "ChannelInfo,ChannelImage" - }).then(function(result) { - result.Items.length && result.Items[0].SeriesTimerId != seriesTimerId && (result.Items = []); - var html = getProgramScheduleHtml(result.Items), - scheduleTab = page.querySelector(".seriesTimerSchedule"); - scheduleTab.innerHTML = html, imageLoader.lazyChildren(scheduleTab) - }) + }).then(function (result) { + if (result.Items.length && result.Items[0].SeriesTimerId != seriesTimerId) { + result.Items = []; + } + + var html = getProgramScheduleHtml(result.Items); + var scheduleTab = page.querySelector(".seriesTimerSchedule"); + scheduleTab.innerHTML = html; + imageLoader.lazyChildren(scheduleTab); + }); } function renderTimerEditor(page, item, apiClient, user) { - if ("Recording" !== item.Type || !user.Policy.EnableLiveTvManagement || !item.TimerId || "InProgress" !== item.Status) return void hideAll(page, "btnCancelTimer"); - hideAll(page, "btnCancelTimer", !0) + if ("Recording" !== item.Type || !user.Policy.EnableLiveTvManagement || !item.TimerId || "InProgress" !== item.Status) { + return void hideAll(page, "btnCancelTimer"); + } + + hideAll(page, "btnCancelTimer", true); } function renderSeriesTimerEditor(page, item, apiClient, user) { - return "SeriesTimer" !== item.Type ? void hideAll(page, "btnCancelSeriesTimer") : user.Policy.EnableLiveTvManagement ? (require(["seriesRecordingEditor"], function(seriesRecordingEditor) { - seriesRecordingEditor.embed(item, apiClient.serverId(), { - context: page.querySelector(".seriesRecordingEditor") - }) - }), page.querySelector(".seriesTimerScheduleSection").classList.remove("hide"), hideAll(page, "btnCancelSeriesTimer", !0), void renderSeriesTimerSchedule(page, apiClient, item.Id)) : (page.querySelector(".seriesTimerScheduleSection").classList.add("hide"), void hideAll(page, "btnCancelSeriesTimer")) + if ("SeriesTimer" !== item.Type) { + return void hideAll(page, "btnCancelSeriesTimer"); + } + + if (user.Policy.EnableLiveTvManagement) { + require(["seriesRecordingEditor"], function (seriesRecordingEditor) { + seriesRecordingEditor.embed(item, apiClient.serverId(), { + context: page.querySelector(".seriesRecordingEditor") + }); + }); + + page.querySelector(".seriesTimerScheduleSection").classList.remove("hide"); + hideAll(page, "btnCancelSeriesTimer", true); + return void renderSeriesTimerSchedule(page, apiClient, item.Id); + } + + page.querySelector(".seriesTimerScheduleSection").classList.add("hide"); + return void hideAll(page, "btnCancelSeriesTimer"); } function renderTrackSelections(page, instance, item, forceReload) { var select = page.querySelector(".selectSource"); - if (!item.MediaSources || !itemHelper.supportsMediaSourceSelection(item) || -1 === playbackManager.getSupportedCommands().indexOf("PlayMediaSource") || !playbackManager.canPlay(item)) return page.querySelector(".trackSelections").classList.add("hide"), select.innerHTML = "", page.querySelector(".selectVideo").innerHTML = "", page.querySelector(".selectAudio").innerHTML = "", void(page.querySelector(".selectSubtitles").innerHTML = ""); - playbackManager.getPlaybackMediaSources(item).then(function(mediaSources) { - instance._currentPlaybackMediaSources = mediaSources, page.querySelector(".trackSelections").classList.remove("hide"), select.setLabel(globalize.translate("LabelVersion")); - var currentValue = select.value, - selectedId = mediaSources[0].Id; - select.innerHTML = mediaSources.map(function(v) { + + if (!item.MediaSources || !itemHelper.supportsMediaSourceSelection(item) || -1 === playbackManager.getSupportedCommands().indexOf("PlayMediaSource") || !playbackManager.canPlay(item)) { + page.querySelector(".trackSelections").classList.add("hide"); + select.innerHTML = ""; + page.querySelector(".selectVideo").innerHTML = ""; + page.querySelector(".selectAudio").innerHTML = ""; + page.querySelector(".selectSubtitles").innerHTML = ""; + return; + } + + playbackManager.getPlaybackMediaSources(item).then(function (mediaSources) { + instance._currentPlaybackMediaSources = mediaSources; + page.querySelector(".trackSelections").classList.remove("hide"); + select.setLabel(globalize.translate("LabelVersion")); + var currentValue = select.value; + var selectedId = mediaSources[0].Id; + select.innerHTML = mediaSources.map(function (v) { var selected = v.Id === selectedId ? " selected" : ""; - return '" - }).join(""), mediaSources.length > 1 ? page.querySelector(".selectSourceContainer").classList.remove("hide") : page.querySelector(".selectSourceContainer").classList.add("hide"), (select.value !== currentValue || forceReload) && (renderVideoSelections(page, mediaSources), renderAudioSelections(page, mediaSources), renderSubtitleSelections(page, mediaSources)) - }) + return '"; + }).join(""); + + if (mediaSources.length > 1) { + page.querySelector(".selectSourceContainer").classList.remove("hide"); + } else { + page.querySelector(".selectSourceContainer").classList.add("hide"); + } + + if (select.value !== currentValue || forceReload) { + renderVideoSelections(page, mediaSources); + renderAudioSelections(page, mediaSources); + renderSubtitleSelections(page, mediaSources); + } + }); } function renderVideoSelections(page, mediaSources) { - var mediaSourceId = page.querySelector(".selectSource").value, - mediaSource = mediaSources.filter(function(m) { - return m.Id === mediaSourceId - })[0], - tracks = mediaSource.MediaStreams.filter(function(m) { - return "Video" === m.Type - }), - select = page.querySelector(".selectVideo"); + var mediaSourceId = page.querySelector(".selectSource").value; + var mediaSource = mediaSources.filter(function (m) { + return m.Id === mediaSourceId; + })[0]; + var tracks = mediaSource.MediaStreams.filter(function (m) { + return "Video" === m.Type; + }); + var select = page.querySelector(".selectVideo"); select.setLabel(globalize.translate("LabelVideo")); var selectedId = tracks.length ? tracks[0].Index : -1; - select.innerHTML = tracks.map(function(v) { - var selected = v.Index === selectedId ? " selected" : "", - titleParts = [], - resolutionText = mediaInfo.getResolutionText(v); - return resolutionText && titleParts.push(resolutionText), v.Codec && titleParts.push(v.Codec.toUpperCase()), '" - }).join(""), select.setAttribute("disabled", "disabled"), tracks.length ? page.querySelector(".selectVideoContainer").classList.remove("hide") : page.querySelector(".selectVideoContainer").classList.add("hide") + select.innerHTML = tracks.map(function (v) { + var selected = v.Index === selectedId ? " selected" : ""; + var titleParts = []; + var resolutionText = mediaInfo.getResolutionText(v); + + if (resolutionText) { + titleParts.push(resolutionText); + } + + if (v.Codec) { + titleParts.push(v.Codec.toUpperCase()); + } + + return '"; + }).join(""); + select.setAttribute("disabled", "disabled"); + + if (tracks.length) { + page.querySelector(".selectVideoContainer").classList.remove("hide"); + } else { + page.querySelector(".selectVideoContainer").classList.add("hide"); + } } function renderAudioSelections(page, mediaSources) { - var mediaSourceId = page.querySelector(".selectSource").value, - mediaSource = mediaSources.filter(function(m) { - return m.Id === mediaSourceId - })[0], - tracks = mediaSource.MediaStreams.filter(function(m) { - return "Audio" === m.Type - }), - select = page.querySelector(".selectAudio"); + var mediaSourceId = page.querySelector(".selectSource").value; + var mediaSource = mediaSources.filter(function (m) { + return m.Id === mediaSourceId; + })[0]; + var tracks = mediaSource.MediaStreams.filter(function (m) { + return "Audio" === m.Type; + }); + var select = page.querySelector(".selectAudio"); select.setLabel(globalize.translate("LabelAudio")); var selectedId = mediaSource.DefaultAudioStreamIndex; - select.innerHTML = tracks.map(function(v) { + select.innerHTML = tracks.map(function (v) { var selected = v.Index === selectedId ? " selected" : ""; - return '" - }).join(""), tracks.length > 1 ? select.removeAttribute("disabled") : select.setAttribute("disabled", "disabled"), tracks.length ? page.querySelector(".selectAudioContainer").classList.remove("hide") : page.querySelector(".selectAudioContainer").classList.add("hide") + return '"; + }).join(""); + + if (tracks.length > 1) { + select.removeAttribute("disabled"); + } else { + select.setAttribute("disabled", "disabled"); + } + + if (tracks.length) { + page.querySelector(".selectAudioContainer").classList.remove("hide"); + } else { + page.querySelector(".selectAudioContainer").classList.add("hide"); + } } function renderSubtitleSelections(page, mediaSources) { - var mediaSourceId = page.querySelector(".selectSource").value, - mediaSource = mediaSources.filter(function(m) { - return m.Id === mediaSourceId - })[0], - tracks = mediaSource.MediaStreams.filter(function(m) { - return "Subtitle" === m.Type - }), - select = page.querySelector(".selectSubtitles"); + var mediaSourceId = page.querySelector(".selectSource").value; + var mediaSource = mediaSources.filter(function (m) { + return m.Id === mediaSourceId; + })[0]; + var tracks = mediaSource.MediaStreams.filter(function (m) { + return "Subtitle" === m.Type; + }); + var select = page.querySelector(".selectSubtitles"); select.setLabel(globalize.translate("LabelSubtitles")); var selectedId = null == mediaSource.DefaultSubtitleStreamIndex ? -1 : mediaSource.DefaultSubtitleStreamIndex; + if (tracks.length) { var selected = -1 === selectedId ? " selected" : ""; - select.innerHTML = '" + tracks.map(function(v) { - return selected = v.Index === selectedId ? " selected" : "", '" - }).join(""), page.querySelector(".selectSubtitlesContainer").classList.remove("hide") - } else select.innerHTML = "", page.querySelector(".selectSubtitlesContainer").classList.add("hide") + select.innerHTML = '" + tracks.map(function (v) { + selected = v.Index === selectedId ? " selected" : ""; + return '"; + }).join(""); + page.querySelector(".selectSubtitlesContainer").classList.remove("hide"); + } else { + select.innerHTML = ""; + page.querySelector(".selectSubtitlesContainer").classList.add("hide"); + } } function reloadPlayButtons(page, item) { - var canPlay = !1; + var canPlay = false; + if ("Program" == item.Type) { - var now = new Date; - now >= datetime.parseISO8601Date(item.StartDate, !0) && now < datetime.parseISO8601Date(item.EndDate, !0) ? (hideAll(page, "btnPlay", !0), canPlay = !0) : hideAll(page, "btnPlay"), hideAll(page, "btnResume"), hideAll(page, "btnInstantMix"), hideAll(page, "btnShuffle") + var now = new Date(); + + if (now >= datetime.parseISO8601Date(item.StartDate, true) && now < datetime.parseISO8601Date(item.EndDate, true)) { + hideAll(page, "btnPlay", true); + canPlay = true; + } else { + hideAll(page, "btnPlay"); + } + + hideAll(page, "btnResume"); + hideAll(page, "btnInstantMix"); + hideAll(page, "btnShuffle"); } else if (playbackManager.canPlay(item)) { - hideAll(page, "btnPlay", !0); + hideAll(page, "btnPlay", true); var enableInstantMix = -1 !== ["Audio", "MusicAlbum", "MusicGenre", "MusicArtist"].indexOf(item.Type); hideAll(page, "btnInstantMix", enableInstantMix); var enableShuffle = item.IsFolder || -1 !== ["MusicAlbum", "MusicGenre", "MusicArtist"].indexOf(item.Type); - hideAll(page, "btnShuffle", enableShuffle), canPlay = !0, hideAll(page, "btnResume", item.UserData && item.UserData.PlaybackPositionTicks > 0) - } else hideAll(page, "btnPlay"), hideAll(page, "btnResume"), hideAll(page, "btnInstantMix"), hideAll(page, "btnShuffle"); - return canPlay + hideAll(page, "btnShuffle", enableShuffle); + canPlay = true; + hideAll(page, "btnResume", item.UserData && item.UserData.PlaybackPositionTicks > 0); + } else { + hideAll(page, "btnPlay"); + hideAll(page, "btnResume"); + hideAll(page, "btnInstantMix"); + hideAll(page, "btnShuffle"); + } + + return canPlay; } function reloadUserDataButtons(page, item) { - var i, length, btnPlaystates = page.querySelectorAll(".btnPlaystate"); + var i; + var length; + var btnPlaystates = page.querySelectorAll(".btnPlaystate"); + for (i = 0, length = btnPlaystates.length; i < length; i++) { var btnPlaystate = btnPlaystates[i]; - itemHelper.canMarkPlayed(item) ? (btnPlaystate.classList.remove("hide"), btnPlaystate.setItem(item)) : (btnPlaystate.classList.add("hide"), btnPlaystate.setItem(null)) + + if (itemHelper.canMarkPlayed(item)) { + btnPlaystate.classList.remove("hide"); + btnPlaystate.setItem(item); + } else { + btnPlaystate.classList.add("hide"); + btnPlaystate.setItem(null); + } } + var btnUserRatings = page.querySelectorAll(".btnUserRating"); + for (i = 0, length = btnUserRatings.length; i < length; i++) { var btnUserRating = btnUserRatings[i]; - itemHelper.canRate(item) ? (btnUserRating.classList.remove("hide"), btnUserRating.setItem(item)) : (btnUserRating.classList.add("hide"), btnUserRating.setItem(null)) + + if (itemHelper.canRate(item)) { + btnUserRating.classList.remove("hide"); + btnUserRating.setItem(item); + } else { + btnUserRating.classList.add("hide"); + btnUserRating.setItem(null); + } } } function getArtistLinksHtml(artists, serverId, context) { - for (var html = [], i = 0, length = artists.length; i < length; i++) { - var artist = artists[i], - href = appRouter.getRouteUrl(artist, { - context: context, - itemType: "MusicArtist", - serverId: serverId - }); - html.push('' + artist.Name + "") + var html = []; + + for (var i = 0, length = artists.length; i < length; i++) { + var artist = artists[i]; + var href = appRouter.getRouteUrl(artist, { + context: context, + itemType: "MusicArtist", + serverId: serverId + }); + html.push('' + artist.Name + ""); } - return html = html.join(" / ") + + return html = html.join(" / "); } function renderName(item, container, isStatic, context) { - var parentRoute, parentNameHtml = [], - parentNameLast = !1; - item.AlbumArtists ? (parentNameHtml.push(getArtistLinksHtml(item.AlbumArtists, item.ServerId, context)), parentNameLast = !0) : item.ArtistItems && item.ArtistItems.length && "MusicVideo" === item.Type ? (parentNameHtml.push(getArtistLinksHtml(item.ArtistItems, item.ServerId, context)), parentNameLast = !0) : item.SeriesName && "Episode" === item.Type ? (parentRoute = appRouter.getRouteUrl({ - Id: item.SeriesId, - Name: item.SeriesName, - Type: "Series", - IsFolder: !0, - ServerId: item.ServerId - }, { - context: context - }), parentNameHtml.push('' + item.SeriesName + "")) : (item.IsSeries || item.EpisodeTitle) && parentNameHtml.push(item.Name), item.SeriesName && "Season" === item.Type ? (parentRoute = appRouter.getRouteUrl({ - Id: item.SeriesId, - Name: item.SeriesName, - Type: "Series", - IsFolder: !0, - ServerId: item.ServerId - }, { - context: context - }), parentNameHtml.push('' + item.SeriesName + "")) : null != item.ParentIndexNumber && "Episode" === item.Type ? (parentRoute = appRouter.getRouteUrl({ - Id: item.SeasonId, - Name: item.SeasonName, - Type: "Season", - IsFolder: !0, - ServerId: item.ServerId - }, { - context: context - }), parentNameHtml.push('' + item.SeasonName + "")) : null != item.ParentIndexNumber && item.IsSeries ? parentNameHtml.push(item.SeasonName || "S" + item.ParentIndexNumber) : item.Album && item.AlbumId && ("MusicVideo" === item.Type || "Audio" === item.Type) ? (parentRoute = appRouter.getRouteUrl({ - Id: item.AlbumId, - Name: item.Album, - Type: "MusicAlbum", - IsFolder: !0, - ServerId: item.ServerId - }, { - context: context - }), parentNameHtml.push('' + item.Album + "")) : item.Album && parentNameHtml.push(item.Album); - var html = ""; - parentNameHtml.length && (html = parentNameLast ? '

            ' + parentNameHtml.join(" - ") + "

            " : '

            ' + parentNameHtml.join(" - ") + "

            "); - var name = itemHelper.getDisplayName(item, { - includeParentInfo: !1 - }); + var parentRoute; + var parentNameHtml = []; + var parentNameLast = false; + if (item.AlbumArtists) { + parentNameHtml.push(getArtistLinksHtml(item.AlbumArtists, item.ServerId, context)); + parentNameLast = true; + } else if (item.ArtistItems && item.ArtistItems.length && "MusicVideo" === item.Type) { + parentNameHtml.push(getArtistLinksHtml(item.ArtistItems, item.ServerId, context)); + parentNameLast = true; + } else if (item.SeriesName && "Episode" === item.Type) { + parentRoute = appRouter.getRouteUrl({ + Id: item.SeriesId, + Name: item.SeriesName, + Type: "Series", + IsFolder: true, + ServerId: item.ServerId + }, { + context: context + }); + parentNameHtml.push('' + item.SeriesName + ""); + } else if (item.IsSeries || item.EpisodeTitle) { + parentNameHtml.push(item.Name); + } + + if (item.SeriesName && "Season" === item.Type) { + parentRoute = appRouter.getRouteUrl({ + Id: item.SeriesId, + Name: item.SeriesName, + Type: "Series", + IsFolder: true, + ServerId: item.ServerId + }, { + context: context + }); + parentNameHtml.push('' + item.SeriesName + ""); + } else if (null != item.ParentIndexNumber && "Episode" === item.Type) { + parentRoute = appRouter.getRouteUrl({ + Id: item.SeasonId, + Name: item.SeasonName, + Type: "Season", + IsFolder: true, + ServerId: item.ServerId + }, { + context: context + }); + parentNameHtml.push('' + item.SeasonName + ""); + } else if (null != item.ParentIndexNumber && item.IsSeries) { + parentNameHtml.push(item.SeasonName || "S" + item.ParentIndexNumber); + } else if (item.Album && item.AlbumId && ("MusicVideo" === item.Type || "Audio" === item.Type)) { + parentRoute = appRouter.getRouteUrl({ + Id: item.AlbumId, + Name: item.Album, + Type: "MusicAlbum", + IsFolder: true, + ServerId: item.ServerId + }, { + context: context + }); + parentNameHtml.push('' + item.Album + ""); + } else if (item.Album) { + parentNameHtml.push(item.Album); + } + + var html = ""; + + if (parentNameHtml.length) { + if (parentNameLast) { + html = '

            ' + parentNameHtml.join(" - ") + "

            "; + } else { + html = '

            ' + parentNameHtml.join(" - ") + "

            "; + } + } + + var name = itemHelper.getDisplayName(item, { + includeParentInfo: false + }); var offset = parentNameLast ? ".25em" : ".5em"; + if (html && !parentNameLast) { html += '

            ' + name + '

            '; } else { @@ -248,110 +429,206 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild } container.innerHTML = html; - html.length ? container.classList.remove("hide") : container.classList.add("hide") + + if (html.length) { + container.classList.remove("hide"); + } else { + container.classList.add("hide"); + } } function setTrailerButtonVisibility(page, item) { - (item.LocalTrailerCount || item.RemoteTrailers && item.RemoteTrailers.length) && -1 !== playbackManager.getSupportedCommands().indexOf("PlayTrailers") ? hideAll(page, "btnPlayTrailer", !0) : hideAll(page, "btnPlayTrailer") - } - - function renderDetailPageBackdrop(page, item, apiClient) { - var imgUrl, screenWidth = screen.availWidth, - hasbackdrop = !1, - itemBackdropElement = page.querySelector("#itemBackdrop"), - usePrimaryImage = ("Video" === item.MediaType && "Movie" !== item.Type && "Trailer" !== item.Type) || (item.MediaType && "Video" !== item.MediaType) || ("MusicAlbum" === item.Type) || ("MusicArtist" === item.Type); - return "Program" === item.Type && item.ImageTags && item.ImageTags.Thumb ? (imgUrl = apiClient.getScaledImageUrl(item.Id, { - type: "Thumb", - index: 0, - maxWidth: screenWidth, - tag: item.ImageTags.Thumb - }), itemBackdropElement.classList.remove("noBackdrop"), imageLoader.lazyImage(itemBackdropElement, imgUrl, !1), hasbackdrop = !0) : usePrimaryImage && item.ImageTags && item.ImageTags.Primary ? (imgUrl = apiClient.getScaledImageUrl(item.Id, { - type: "Primary", - index: 0, - maxWidth: screenWidth, - tag: item.ImageTags.Primary - }), itemBackdropElement.classList.remove("noBackdrop"), imageLoader.lazyImage(itemBackdropElement, imgUrl, !1), hasbackdrop = !0) : item.BackdropImageTags && item.BackdropImageTags.length ? (imgUrl = apiClient.getScaledImageUrl(item.Id, { - type: "Backdrop", - index: 0, - maxWidth: screenWidth, - tag: item.BackdropImageTags[0] - }), itemBackdropElement.classList.remove("noBackdrop"), imageLoader.lazyImage(itemBackdropElement, imgUrl, !1), hasbackdrop = !0) : item.ParentBackdropItemId && item.ParentBackdropImageTags && item.ParentBackdropImageTags.length ? (imgUrl = apiClient.getScaledImageUrl(item.ParentBackdropItemId, { - type: "Backdrop", - index: 0, - tag: item.ParentBackdropImageTags[0], - maxWidth: screenWidth - }), itemBackdropElement.classList.remove("noBackdrop"), imageLoader.lazyImage(itemBackdropElement, imgUrl, !1), hasbackdrop = !0) : item.ImageTags && item.ImageTags.Thumb ? (imgUrl = apiClient.getScaledImageUrl(item.Id, { - type: "Thumb", - index: 0, - maxWidth: screenWidth, - tag: item.ImageTags.Thumb - }), itemBackdropElement.classList.remove("noBackdrop"), imageLoader.lazyImage(itemBackdropElement, imgUrl, !1), hasbackdrop = !0) : (itemBackdropElement.classList.add("noBackdrop"), itemBackdropElement.style.backgroundImage = ""), hasbackdrop - } - - function reloadFromItem(instance, page, params, item, user) { - var context = params.context; - renderName(item, page.querySelector(".nameContainer"), !1, context); - var apiClient = connectionManager.getApiClient(item.ServerId); - renderSeriesTimerEditor(page, item, apiClient, user), renderTimerEditor(page, item, apiClient, user), renderImage(page, item, apiClient, user), renderLogo(page, item, apiClient), setTitle(item, apiClient), setInitialCollapsibleState(page, item, apiClient, context, user), renderDetails(page, item, apiClient, context), renderTrackSelections(page, instance, item), dom.getWindowSize().innerWidth >= 1e3 ? backdrop.setBackdrops([item]) : backdrop.clear(), renderDetailPageBackdrop(page, item, apiClient); - var canPlay = reloadPlayButtons(page, item); if ((item.LocalTrailerCount || item.RemoteTrailers && item.RemoteTrailers.length) && -1 !== playbackManager.getSupportedCommands().indexOf("PlayTrailers")) { hideAll(page, "btnPlayTrailer", true); } else { hideAll(page, "btnPlayTrailer"); } + } + + function renderDetailPageBackdrop(page, item, apiClient) { + var imgUrl; + var screenWidth = screen.availWidth; + var hasbackdrop = false; + var itemBackdropElement = page.querySelector("#itemBackdrop"); + var usePrimaryImage = item.MediaType === "Video" && item.Type !== "Movie" && item.Type !== "Trailer" || + item.MediaType && item.MediaType !== "Video" || + item.Type === "MusicAlbum" || + item.Type === "MusicArtist"; + + if ("Program" === item.Type && item.ImageTags && item.ImageTags.Thumb) { + imgUrl = apiClient.getScaledImageUrl(item.Id, { + type: "Thumb", + index: 0, + maxWidth: screenWidth, + tag: item.ImageTags.Thumb + }); + itemBackdropElement.classList.remove("noBackdrop"); + imageLoader.lazyImage(itemBackdropElement, imgUrl, false); + hasbackdrop = true; + } else if (usePrimaryImage && item.ImageTags && item.ImageTags.Primary) { + imgUrl = apiClient.getScaledImageUrl(item.Id, { + type: "Primary", + index: 0, + maxWidth: screenWidth, + tag: item.ImageTags.Primary + }); + itemBackdropElement.classList.remove("noBackdrop"); + imageLoader.lazyImage(itemBackdropElement, imgUrl, false); + hasbackdrop = true; + } else if (item.BackdropImageTags && item.BackdropImageTags.length) { + imgUrl = apiClient.getScaledImageUrl(item.Id, { + type: "Backdrop", + index: 0, + maxWidth: screenWidth, + tag: item.BackdropImageTags[0] + }); + itemBackdropElement.classList.remove("noBackdrop"); + imageLoader.lazyImage(itemBackdropElement, imgUrl, false); + hasbackdrop = true; + } else if (item.ParentBackdropItemId && item.ParentBackdropImageTags && item.ParentBackdropImageTags.length) { + imgUrl = apiClient.getScaledImageUrl(item.ParentBackdropItemId, { + type: "Backdrop", + index: 0, + tag: item.ParentBackdropImageTags[0], + maxWidth: screenWidth + }); + itemBackdropElement.classList.remove("noBackdrop"); + imageLoader.lazyImage(itemBackdropElement, imgUrl, false); + hasbackdrop = true; + } else if (item.ImageTags && item.ImageTags.Thumb) { + imgUrl = apiClient.getScaledImageUrl(item.Id, { + type: "Thumb", + index: 0, + maxWidth: screenWidth, + tag: item.ImageTags.Thumb + }); + itemBackdropElement.classList.remove("noBackdrop"); + imageLoader.lazyImage(itemBackdropElement, imgUrl, false); + hasbackdrop = true; + } else { + itemBackdropElement.classList.add("noBackdrop"); + itemBackdropElement.style.backgroundImage = ""; + } + + return hasbackdrop; + } + + function reloadFromItem(instance, page, params, item, user) { + var context = params.context; + renderName(item, page.querySelector(".nameContainer"), false, context); + var apiClient = connectionManager.getApiClient(item.ServerId); + renderSeriesTimerEditor(page, item, apiClient, user); + renderTimerEditor(page, item, apiClient, user); + renderImage(page, item, apiClient, user); + renderLogo(page, item, apiClient); + setTitle(item, apiClient); + setInitialCollapsibleState(page, item, apiClient, context, user); + renderDetails(page, item, apiClient, context); + renderTrackSelections(page, instance, item); + + if (dom.getWindowSize().innerWidth >= 1000) { + backdrop.setBackdrops([item]); + } else { + backdrop.clear(); + } + + renderDetailPageBackdrop(page, item, apiClient); + var canPlay = reloadPlayButtons(page, item); + + if ((item.LocalTrailerCount || item.RemoteTrailers && item.RemoteTrailers.length) && -1 !== playbackManager.getSupportedCommands().indexOf("PlayTrailers")) { + hideAll(page, "btnPlayTrailer", true); + } else { + hideAll(page, "btnPlayTrailer"); + } + setTrailerButtonVisibility(page, item); + if (item.CanDelete && !item.IsFolder) { hideAll(page, "btnDeleteItem", true); } else { hideAll(page, "btnDeleteItem"); } + if ("Program" !== item.Type || canPlay) { hideAll(page, "mainDetailButtons", true); } else { hideAll(page, "mainDetailButtons"); } + showRecordingFields(instance, page, item, user); - var groupedVersions = (item.MediaSources || []).filter(function(g) { - return "Grouping" == g.Type + var groupedVersions = (item.MediaSources || []).filter(function (g) { + return "Grouping" == g.Type; }); - user.Policy.IsAdministrator && groupedVersions.length ? page.querySelector(".btnSplitVersions").classList.remove("hide") : page.querySelector(".btnSplitVersions").classList.add("hide"), itemContextMenu.getCommands(getContextMenuOptions(item, user)).length ? hideAll(page, "btnMoreCommands", !0) : hideAll(page, "btnMoreCommands"); - var itemBirthday = page.querySelector("#itemBirthday"); - if ("Person" == item.Type && item.PremiereDate) try { - var birthday = datetime.parseISO8601Date(item.PremiereDate, !0).toDateString(); - itemBirthday.classList.remove("hide"), itemBirthday.innerHTML = globalize.translate("BirthDateValue").replace("{0}", birthday) - } catch (err) { - itemBirthday.classList.add("hide") - } else itemBirthday.classList.add("hide"); - var itemDeathDate = page.querySelector("#itemDeathDate"); - if ("Person" == item.Type && item.EndDate) try { - var deathday = datetime.parseISO8601Date(item.EndDate, !0).toDateString(); - itemDeathDate.classList.remove("hide"), itemDeathDate.innerHTML = globalize.translate("DeathDateValue").replace("{0}", deathday) - } catch (err) { - itemDeathDate.classList.add("hide") + + if (user.Policy.IsAdministrator && groupedVersions.length) { + page.querySelector(".btnSplitVersions").classList.remove("hide"); + } else { + page.querySelector(".btnSplitVersions").classList.add("hide"); } + + if (itemContextMenu.getCommands(getContextMenuOptions(item, user)).length) { + hideAll(page, "btnMoreCommands", true); + } else { + hideAll(page, "btnMoreCommands"); + } + + var itemBirthday = page.querySelector("#itemBirthday"); + + if ("Person" == item.Type && item.PremiereDate) { + try { + var birthday = datetime.parseISO8601Date(item.PremiereDate, true).toDateString(); + itemBirthday.classList.remove("hide"); + itemBirthday.innerHTML = globalize.translate("BirthDateValue").replace("{0}", birthday); + } catch (err) { + itemBirthday.classList.add("hide"); + } + } else { + itemBirthday.classList.add("hide"); + } + + var itemDeathDate = page.querySelector("#itemDeathDate"); + + if ("Person" == item.Type && item.EndDate) { + try { + var deathday = datetime.parseISO8601Date(item.EndDate, true).toDateString(); + itemDeathDate.classList.remove("hide"); + itemDeathDate.innerHTML = globalize.translate("DeathDateValue").replace("{0}", deathday); + } catch (err) { + itemDeathDate.classList.add("hide"); + } + } else { + itemDeathDate.classList.add("hide"); + } + var itemBirthLocation = page.querySelector("#itemBirthLocation"); + if ("Person" == item.Type && item.ProductionLocations && item.ProductionLocations.length) { var gmap = '' + item.ProductionLocations[0] + ""; - itemBirthLocation.classList.remove("hide"), itemBirthLocation.innerHTML = globalize.translate("BirthPlaceValue").replace("{0}", gmap) - } else itemBirthLocation.classList.add("hide"); - setPeopleHeader(page, item), loading.hide() + itemBirthLocation.classList.remove("hide"); + itemBirthLocation.innerHTML = globalize.translate("BirthPlaceValue").replace("{0}", gmap); + } else { + itemBirthLocation.classList.add("hide"); + } + + setPeopleHeader(page, item); + loading.hide(); if (item.Type === "Book") { hideAll(page, "btnDownload", true); } try { - require(["focusManager"], function(focusManager) { + require(["focusManager"], function (focusManager) { [".btnResume", ".btnPlay"].every(function (cls) { - var elems = page.querySelectorAll(cls); - + for (var i = 0; i < elems.length; i++) { if (focusManager.isCurrentlyFocusable(elems[i])) { focusManager.focus(elems[i]); return false; } } + return true; }); }); @@ -361,35 +638,68 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild } function logoImageUrl(item, apiClient, options) { - return options = options || {}, options.type = "Logo", item.ImageTags && item.ImageTags.Logo ? (options.tag = item.ImageTags.Logo, apiClient.getScaledImageUrl(item.Id, options)) : item.ParentLogoImageTag ? (options.tag = item.ParentLogoImageTag, apiClient.getScaledImageUrl(item.ParentLogoItemId, options)) : null + options = options || {}; + options.type = "Logo"; + + if (item.ImageTags && item.ImageTags.Logo) { + options.tag = item.ImageTags.Logo; + return apiClient.getScaledImageUrl(item.Id, options); + } + + if (item.ParentLogoImageTag) { + options.tag = item.ParentLogoImageTag; + return apiClient.getScaledImageUrl(item.ParentLogoItemId, options); + } + + return null; } function setTitle(item, apiClient) { var url = logoImageUrl(item, apiClient, {}); + if (url = null) { var pageTitle = document.querySelector(".pageTitle"); - pageTitle.style.backgroundImage = "url('" + url + "')", pageTitle.classList.add("pageTitleWithLogo"), pageTitle.innerHTML = "" - } else Emby.Page.setTitle("") + pageTitle.style.backgroundImage = "url('" + url + "')"; + pageTitle.classList.add("pageTitleWithLogo"); + pageTitle.innerHTML = ""; + } else { + Emby.Page.setTitle(""); + } } function renderLogo(page, item, apiClient) { var url = logoImageUrl(item, apiClient, { - maxWidth: 400 - }), - detailLogo = page.querySelector(".detailLogo"); - url ? (detailLogo.classList.remove("hide"), detailLogo.classList.add("lazy"), detailLogo.setAttribute("data-src", url), imageLoader.lazyImage(detailLogo)) : detailLogo.classList.add("hide") + maxWidth: 400 + }); + var detailLogo = page.querySelector(".detailLogo"); + + if (url) { + detailLogo.classList.remove("hide"); + detailLogo.classList.add("lazy"); + detailLogo.setAttribute("data-src", url); + imageLoader.lazyImage(detailLogo); + } else { + detailLogo.classList.add("hide"); + } } function showRecordingFields(instance, page, item, user) { if (!instance.currentRecordingFields) { var recordingFieldsElement = page.querySelector(".recordingFields"); - "Program" == item.Type && user.Policy.EnableLiveTvManagement ? require(["recordingFields"], function(recordingFields) { - instance.currentRecordingFields = new recordingFields({ - parent: recordingFieldsElement, - programId: item.Id, - serverId: item.ServerId - }), recordingFieldsElement.classList.remove("hide") - }) : (recordingFieldsElement.classList.add("hide"), recordingFieldsElement.innerHTML = "") + + if ("Program" == item.Type && user.Policy.EnableLiveTvManagement) { + require(["recordingFields"], function (recordingFields) { + instance.currentRecordingFields = new recordingFields({ + parent: recordingFieldsElement, + programId: item.Id, + serverId: item.ServerId + }); + recordingFieldsElement.classList.remove("hide"); + }); + } else { + recordingFieldsElement.classList.add("hide"); + recordingFieldsElement.innerHTML = ""; + } } } @@ -399,7 +709,7 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild if (item.UserData && item.UserData.LastPlayedDate) { lastPlayedElement.classList.remove("hide"); var datePlayed = datetime.parseISO8601Date(item.UserData.LastPlayedDate); - lastPlayedElement.innerHTML = globalize.translate("DatePlayed") + " " + datetime.toLocaleDateString(datePlayed) + " " + datetime.getDisplayTime(datePlayed); + lastPlayedElement.innerHTML = globalize.translate("DatePlayed") + ": " + datetime.toLocaleDateString(datePlayed) + " " + datetime.getDisplayTime(datePlayed); } else { lastPlayedElement.classList.add("hide"); } @@ -407,145 +717,340 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild function renderLinks(linksElem, item) { var html = []; + if (item.DateCreated && itemHelper.enableDateAddedDisplay(item)) { var dateCreated = datetime.parseISO8601Date(item.DateCreated); - html.push(globalize.translate("AddedOnValue", datetime.toLocaleDateString(dateCreated) + " " + datetime.getDisplayTime(dateCreated))) + html.push(globalize.translate("AddedOnValue", datetime.toLocaleDateString(dateCreated) + " " + datetime.getDisplayTime(dateCreated))); } + var links = []; - if (!layoutManager.tv && (item.HomePageUrl && links.push('' + globalize.translate("ButtonWebsite") + ""), item.ExternalUrls)) + + if (!layoutManager.tv && item.HomePageUrl) { + links.push('' + globalize.translate("ButtonWebsite") + ""); + } + if (item.ExternalUrls) { for (var i = 0, length = item.ExternalUrls.length; i < length; i++) { var url = item.ExternalUrls[i]; - links.push('' + url.Name + "") + links.push('' + url.Name + ""); } - links.length && html.push(globalize.translate("LinksValue", links.join(", "))), linksElem.innerHTML = html.join(", "), html.length ? linksElem.classList.remove("hide") : linksElem.classList.add("hide") + } + + if (links.length) { + html.push(globalize.translate("LinksValue", links.join(", "))); + } + + linksElem.innerHTML = html.join(", "); + + if (html.length) { + linksElem.classList.remove("hide"); + } else { + linksElem.classList.add("hide"); + } } function renderDetailImage(page, elem, item, apiClient, editable, imageLoader, indicators) { - "SeriesTimer" !== item.Type && "Program" !== item.Type || (editable = !1), "Person" !== item.Type ? (elem.classList.add("detailimg-hidemobile"), page.querySelector(".detailPageContent").classList.add("detailPageContent-nodetailimg")) : page.querySelector(".detailPageContent").classList.remove("detailPageContent-nodetailimg"); + if ("SeriesTimer" === item.Type || "Program" === item.Type) { + editable = false; + } + + if ("Person" !== item.Type) { + elem.classList.add("detailimg-hidemobile"); + page.querySelector(".detailPageContent").classList.add("detailPageContent-nodetailimg"); + } else { + page.querySelector(".detailPageContent").classList.remove("detailPageContent-nodetailimg"); + } + var imageTags = item.ImageTags || {}; - item.PrimaryImageTag && (imageTags.Primary = item.PrimaryImageTag); - var url, html = "", - shape = "portrait", - detectRatio = !1; - imageTags.Primary ? (url = apiClient.getScaledImageUrl(item.Id, { - type: "Primary", - tag: item.ImageTags.Primary - }), detectRatio = !0) : item.BackdropImageTags && item.BackdropImageTags.length ? (url = apiClient.getScaledImageUrl(item.Id, { - type: "Backdrop", - tag: item.BackdropImageTags[0] - }), shape = "thumb") : imageTags.Thumb ? (url = apiClient.getScaledImageUrl(item.Id, { - type: "Thumb", - tag: item.ImageTags.Thumb - }), shape = "thumb") : imageTags.Disc ? (url = apiClient.getScaledImageUrl(item.Id, { - type: "Disc", - tag: item.ImageTags.Disc - }), shape = "square") : item.AlbumId && item.AlbumPrimaryImageTag ? (url = apiClient.getScaledImageUrl(item.AlbumId, { - type: "Primary", - tag: item.AlbumPrimaryImageTag - }), shape = "square") : item.SeriesId && item.SeriesPrimaryImageTag ? url = apiClient.getScaledImageUrl(item.SeriesId, { - type: "Primary", - tag: item.SeriesPrimaryImageTag - }) : item.ParentPrimaryImageItemId && item.ParentPrimaryImageTag && (url = apiClient.getScaledImageUrl(item.ParentPrimaryImageItemId, { - type: "Primary", - tag: item.ParentPrimaryImageTag - })), html += '
            ', editable && (html += ""), detectRatio && item.PrimaryImageAspectRatio && (item.PrimaryImageAspectRatio >= 1.48 ? shape = "thumb" : item.PrimaryImageAspectRatio >= .85 && item.PrimaryImageAspectRatio <= 1.34 && (shape = "square")), html += "", editable && (html += ""); + + if (item.PrimaryImageTag) { + imageTags.Primary = item.PrimaryImageTag; + } + + var url; + var html = ""; + var shape = "portrait"; + var detectRatio = false; + + if (imageTags.Primary) { + url = apiClient.getScaledImageUrl(item.Id, { + type: "Primary", + tag: item.ImageTags.Primary + }); + detectRatio = true; + } else if (item.BackdropImageTags && item.BackdropImageTags.length) { + url = apiClient.getScaledImageUrl(item.Id, { + type: "Backdrop", + tag: item.BackdropImageTags[0] + }); + shape = "thumb"; + } else if (imageTags.Thumb) { + url = apiClient.getScaledImageUrl(item.Id, { + type: "Thumb", + tag: item.ImageTags.Thumb + }); + shape = "thumb"; + } else if (imageTags.Disc) { + url = apiClient.getScaledImageUrl(item.Id, { + type: "Disc", + tag: item.ImageTags.Disc + }); + shape = "square"; + } else if (item.AlbumId && item.AlbumPrimaryImageTag) { + url = apiClient.getScaledImageUrl(item.AlbumId, { + type: "Primary", + tag: item.AlbumPrimaryImageTag + }); + shape = "square"; + } else if (item.SeriesId && item.SeriesPrimaryImageTag) { + url = apiClient.getScaledImageUrl(item.SeriesId, { + type: "Primary", + tag: item.SeriesPrimaryImageTag + }); + } else if (item.ParentPrimaryImageItemId && item.ParentPrimaryImageTag) { + url = apiClient.getScaledImageUrl(item.ParentPrimaryImageItemId, { + type: "Primary", + tag: item.ParentPrimaryImageTag + }); + } + + html += '
            '; + + if (editable) { + html += ""; + } + + if (detectRatio && item.PrimaryImageAspectRatio) { + if (item.PrimaryImageAspectRatio >= 1.48) { + shape = "thumb"; + } else if (item.PrimaryImageAspectRatio >= .85 && item.PrimaryImageAspectRatio <= 1.34) { + shape = "square"; + } + } + + html += ""; + + if (editable) { + html += ""; + } + var progressHtml = item.IsFolder || !item.UserData ? "" : indicators.getProgressBarHtml(item); - html += '
            ', progressHtml && (html += progressHtml), html += "
            ", html += "
            ", elem.innerHTML = html, "thumb" == shape ? (elem.classList.add("thumbDetailImageContainer"), elem.classList.remove("portraitDetailImageContainer"), elem.classList.remove("squareDetailImageContainer")) : "square" == shape ? (elem.classList.remove("thumbDetailImageContainer"), elem.classList.remove("portraitDetailImageContainer"), elem.classList.add("squareDetailImageContainer")) : (elem.classList.remove("thumbDetailImageContainer"), elem.classList.add("portraitDetailImageContainer"), elem.classList.remove("squareDetailImageContainer")), url && imageLoader.lazyImage(elem.querySelector("img"), url) + html += '
            '; + + if (progressHtml) { + html += progressHtml; + } + + html += "
            "; + html += "
            "; + elem.innerHTML = html; + + if ("thumb" == shape) { + elem.classList.add("thumbDetailImageContainer"); + elem.classList.remove("portraitDetailImageContainer"); + elem.classList.remove("squareDetailImageContainer"); + } else if ("square" == shape) { + elem.classList.remove("thumbDetailImageContainer"); + elem.classList.remove("portraitDetailImageContainer"); + elem.classList.add("squareDetailImageContainer"); + } else { + elem.classList.remove("thumbDetailImageContainer"); + elem.classList.add("portraitDetailImageContainer"); + elem.classList.remove("squareDetailImageContainer"); + } + + + if (url) { + imageLoader.lazyImage(elem.querySelector("img"), url); + } } function renderImage(page, item, apiClient, user) { - renderDetailImage(page, page.querySelector(".detailImageContainer"), item, apiClient, user.Policy.IsAdministrator && "Photo" != item.MediaType, imageLoader, indicators) + renderDetailImage( + page, + page.querySelector(".detailImageContainer"), + item, + apiClient, + user.Policy.IsAdministrator && "Photo" != item.MediaType, + imageLoader, + indicators + ); } function refreshDetailImageUserData(elem, item) { - elem.querySelector(".detailImageProgressContainer").innerHTML = indicators.getProgressBarHtml(item) + elem.querySelector(".detailImageProgressContainer").innerHTML = indicators.getProgressBarHtml(item); } function refreshImage(page, item, user) { - refreshDetailImageUserData(page.querySelector(".detailImageContainer"), item) + refreshDetailImageUserData(page.querySelector(".detailImageContainer"), item); } function setPeopleHeader(page, item) { - "Audio" == item.MediaType || "MusicAlbum" == item.Type || "Book" == item.MediaType || "Photo" == item.MediaType ? page.querySelector("#peopleHeader").innerHTML = globalize.translate("HeaderPeople") : page.querySelector("#peopleHeader").innerHTML = globalize.translate("HeaderCastAndCrew") + if ("Audio" == item.MediaType || "MusicAlbum" == item.Type || "Book" == item.MediaType || "Photo" == item.MediaType) { + page.querySelector("#peopleHeader").innerHTML = globalize.translate("HeaderPeople"); + } else { + page.querySelector("#peopleHeader").innerHTML = globalize.translate("HeaderCastAndCrew"); + } } function renderNextUp(page, item, user) { var section = page.querySelector(".nextUpSection"); - if ("Series" != item.Type) return void section.classList.add("hide"); + + if ("Series" != item.Type) { + return void section.classList.add("hide"); + } + connectionManager.getApiClient(item.ServerId).getNextUpEpisodes({ SeriesId: item.Id, UserId: user.Id - }).then(function(result) { - result.Items.length ? section.classList.remove("hide") : section.classList.add("hide"); + }).then(function (result) { + if (result.Items.length) { + section.classList.remove("hide"); + } else { + section.classList.add("hide"); + } + var html = cardBuilder.getCardsHtml({ - items: result.Items, - shape: getThumbShape(!1), - showTitle: !0, - displayAsSpecial: "Season" == item.Type && item.IndexNumber, - overlayText: !1, - centerText: !0, - overlayPlayButton: !0 - }), - itemsContainer = section.querySelector(".nextUpItems"); - itemsContainer.innerHTML = html, imageLoader.lazyChildren(itemsContainer) - }) + items: result.Items, + shape: getThumbShape(false), + showTitle: true, + displayAsSpecial: "Season" == item.Type && item.IndexNumber, + overlayText: false, + centerText: true, + overlayPlayButton: true + }); + var itemsContainer = section.querySelector(".nextUpItems"); + itemsContainer.innerHTML = html; + imageLoader.lazyChildren(itemsContainer); + }); } function setInitialCollapsibleState(page, item, apiClient, context, user) { - page.querySelector(".collectionItems").innerHTML = "", "Playlist" == item.Type ? (page.querySelector("#childrenCollapsible").classList.remove("hide"), renderPlaylistItems(page, item, user)) : "Studio" == item.Type || "Person" == item.Type || "Genre" == item.Type || "MusicGenre" == item.Type || "MusicArtist" == item.Type ? (page.querySelector("#childrenCollapsible").classList.remove("hide"), renderItemsByName(page, item, user)) : item.IsFolder ? ("BoxSet" == item.Type && page.querySelector("#childrenCollapsible").classList.add("hide"), renderChildren(page, item)) : page.querySelector("#childrenCollapsible").classList.add("hide"), "Series" == item.Type && renderSeriesSchedule(page, item, user), "Series" == item.Type ? renderNextUp(page, item, user) : page.querySelector(".nextUpSection").classList.add("hide"), renderScenes(page, item), item.SpecialFeatureCount && 0 != item.SpecialFeatureCount && "Series" != item.Type ? (page.querySelector("#specialsCollapsible").classList.remove("hide"), renderSpecials(page, item, user, 6)) : page.querySelector("#specialsCollapsible").classList.add("hide"), renderCast(page, item, context, enableScrollX() ? null : 12), item.PartCount && item.PartCount > 1 ? (page.querySelector("#additionalPartsCollapsible").classList.remove("hide"), renderAdditionalParts(page, item, user)) : page.querySelector("#additionalPartsCollapsible").classList.add("hide"), "MusicAlbum" == item.Type ? renderMusicVideos(page, item, user) : page.querySelector("#musicVideosCollapsible").classList.add("hide") + page.querySelector(".collectionItems").innerHTML = ""; + + if ("Playlist" == item.Type) { + page.querySelector("#childrenCollapsible").classList.remove("hide"); + renderPlaylistItems(page, item, user); + } else if ("Studio" == item.Type || "Person" == item.Type || "Genre" == item.Type || "MusicGenre" == item.Type || "MusicArtist" == item.Type) { + page.querySelector("#childrenCollapsible").classList.remove("hide"); + renderItemsByName(page, item, user); + } else if (item.IsFolder) { + if ("BoxSet" == item.Type) { + page.querySelector("#childrenCollapsible").classList.add("hide"); + } + + renderChildren(page, item); + } else { + page.querySelector("#childrenCollapsible").classList.add("hide"); + } + + if ("Series" == item.Type) { + renderSeriesSchedule(page, item, user); + renderNextUp(page, item, user); + } else { + page.querySelector(".nextUpSection").classList.add("hide"); + } + + renderScenes(page, item); + + if (item.SpecialFeatureCount && 0 != item.SpecialFeatureCount && "Series" != item.Type) { + page.querySelector("#specialsCollapsible").classList.remove("hide"); + renderSpecials(page, item, user, 6); + } else { + page.querySelector("#specialsCollapsible").classList.add("hide"); + } + + renderCast(page, item, context, enableScrollX() ? null : 12); + + if (item.PartCount && item.PartCount > 1) { + page.querySelector("#additionalPartsCollapsible").classList.remove("hide"); + renderAdditionalParts(page, item, user); + } else { + page.querySelector("#additionalPartsCollapsible").classList.add("hide"); + } + + if ("MusicAlbum" == item.Type) { + renderMusicVideos(page, item, user); + } else { + page.querySelector("#musicVideosCollapsible").classList.add("hide"); + } } function renderOverview(elems, item) { for (var i = 0, length = elems.length; i < length; i++) { - var elem = elems[i], - overview = item.Overview || ""; + var elem = elems[i]; + var overview = item.Overview || ""; + if (overview) { - elem.innerHTML = overview, elem.classList.remove("hide"); - for (var anchors = elem.querySelectorAll("a"), j = 0, length2 = anchors.length; j < length2; j++) anchors[j].setAttribute("target", "_blank") - } else elem.innerHTML = "", elem.classList.add("hide") + elem.innerHTML = overview; + elem.classList.remove("hide"); + var anchors = elem.querySelectorAll("a"); + + for (var j = 0, length2 = anchors.length; j < length2; j++) { + anchors[j].setAttribute("target", "_blank"); + } + } else { + elem.innerHTML = ""; + elem.classList.add("hide"); + } } } function renderGenres(page, item, apiClient, context, isStatic) { context = context || inferContext(item); - var type, genres = item.GenreItems || []; + var type; + var genres = item.GenreItems || []; + switch (context) { case "music": type = "MusicGenre"; break; + default: - type = "Genre" + type = "Genre"; + } + + var html = genres.map(function (p) { + return '' + p.Name + ""; + }).join(", "); + var elem = page.querySelector(".genres"); + elem.innerHTML = globalize.translate(genres.length > 1 ? "GenresValue" : "GenreValue", html); + + if (genres.length) { + elem.classList.remove("hide"); + } else { + elem.classList.add("hide"); } - var html = genres.map(function(p) { - return '' + p.Name + "" - }).join(", "), - elem = page.querySelector(".genres"); - elem.innerHTML = genres.length > 1 ? globalize.translate("GenresValue", html) : globalize.translate("GenreValue", html), genres.length ? elem.classList.remove("hide") : elem.classList.add("hide") } function renderDirector(page, item, apiClient, context, isStatic) { - var directors = (item.People || []).filter(function(p) { - return "Director" === p.Type - }), - html = directors.map(function(p) { - return '' + p.Name + "" - }).join(", "), - elem = page.querySelector(".directors"); - elem.innerHTML = directors.length > 1 ? globalize.translate("DirectorsValue", html) : globalize.translate("DirectorValue", html), directors.length ? elem.classList.remove("hide") : elem.classList.add("hide") + var directors = (item.People || []).filter(function (p) { + return "Director" === p.Type; + }); + var html = directors.map(function (p) { + return '' + p.Name + ""; + }).join(", "); + var elem = page.querySelector(".directors"); + elem.innerHTML = globalize.translate(directors.length > 1 ? "DirectorsValue" : "DirectorValue", html); + + if (directors.length) { + elem.classList.remove("hide"); + } else { + elem.classList.add("hide"); + } } function renderDetails(page, item, apiClient, context, isStatic) { @@ -555,8 +1060,8 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild renderDirector(page, item, apiClient, context, isStatic); renderGenres(page, item, apiClient, context, isStatic); renderChannelGuide(page, apiClient, item); - var taglineElement = page.querySelector(".tagline"); + if (item.Taglines && item.Taglines.length) { taglineElement.classList.remove("hide"); taglineElement.innerHTML = item.Taglines[0]; @@ -571,15 +1076,17 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild overview.classList.add("detailsHiddenOnMobile"); externalLinksElem.classList.add("detailsHiddenOnMobile"); } - renderOverview([overview], item); - var i, itemMiscInfo; + renderOverview([overview], item); + var i; + var itemMiscInfo; itemMiscInfo = page.querySelectorAll(".itemMiscInfo-primary"); + for (i = 0; i < itemMiscInfo.length; i++) { mediaInfo.fillPrimaryMediaInfo(itemMiscInfo[i], item, { - interactive: !0, - episodeTitle: !1, - subtitles: !1 + interactive: true, + episodeTitle: false, + subtitles: false }); if (itemMiscInfo[i].innerHTML && "SeriesTimer" !== item.Type) { @@ -589,11 +1096,12 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild } } - itemMiscInfo = page.querySelectorAll(".itemMiscInfo-secondary") + itemMiscInfo = page.querySelectorAll(".itemMiscInfo-secondary"); + for (i = 0; i < itemMiscInfo.length; i++) { mediaInfo.fillSecondaryMediaInfo(itemMiscInfo[i], item, { - interactive: !0 - }) + interactive: true + }); if (itemMiscInfo[i].innerHTML && "SeriesTimer" !== item.Type) { itemMiscInfo[i].classList.remove("hide"); @@ -601,230 +1109,382 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild itemMiscInfo[i].classList.add("hide"); } } - + reloadUserDataButtons(page, item); renderLinks(externalLinksElem, item); renderUserInfo(page, item); renderTags(page, item); - renderSeriesAirTime(page, item, isStatic) + renderSeriesAirTime(page, item, isStatic); } function enableScrollX() { - return browser.mobile && screen.availWidth <= 1e3 + return browser.mobile && screen.availWidth <= 1000; } function getPortraitShape(scrollX) { - return null == scrollX && (scrollX = enableScrollX()), scrollX ? "overflowPortrait" : "portrait" + if (null == scrollX) { + scrollX = enableScrollX(); + } + + return scrollX ? "overflowPortrait" : "portrait"; } function getSquareShape(scrollX) { - return null == scrollX && (scrollX = enableScrollX()), scrollX ? "overflowSquare" : "square" + if (null == scrollX) { + scrollX = enableScrollX(); + } + + return scrollX ? "overflowSquare" : "square"; } function getThumbShape(scrollX) { - return null == scrollX && (scrollX = enableScrollX()), scrollX ? "overflowBackdrop" : "backdrop" + if (null == scrollX) { + scrollX = enableScrollX(); + } + + return scrollX ? "overflowBackdrop" : "backdrop"; } function renderMoreFromSeason(view, item, apiClient) { var section = view.querySelector(".moreFromSeasonSection"); + if (section) { - if ("Episode" !== item.Type || !item.SeasonId || !item.SeriesId) return void section.classList.add("hide"); + if ("Episode" !== item.Type || !item.SeasonId || !item.SeriesId) { + return void section.classList.add("hide"); + } + var userId = apiClient.getCurrentUserId(); apiClient.getEpisodes(item.SeriesId, { SeasonId: item.SeasonId, UserId: userId, Fields: "ItemCounts,PrimaryImageAspectRatio,BasicSyncInfo,CanDelete,MediaSourceCount" - }).then(function(result) { - if (result.Items.length < 2) return void section.classList.add("hide"); - section.classList.remove("hide"), section.querySelector("h2").innerHTML = globalize.translate("MoreFromValue", item.SeasonName); + }).then(function (result) { + if (result.Items.length < 2) { + return void section.classList.add("hide"); + } + + section.classList.remove("hide"); + section.querySelector("h2").innerHTML = globalize.translate("MoreFromValue", item.SeasonName); var itemsContainer = section.querySelector(".itemsContainer"); cardBuilder.buildCards(result.Items, { parentContainer: section, itemsContainer: itemsContainer, shape: "autooverflow", sectionTitleTagName: "h2", - scalable: !0, - showTitle: !0, - overlayText: !1, - centerText: !0, - includeParentInfoInTitle: !1, - allowBottomPadding: !1 + scalable: true, + showTitle: true, + overlayText: false, + centerText: true, + includeParentInfoInTitle: false, + allowBottomPadding: false }); var card = itemsContainer.querySelector('.card[data-id="' + item.Id + '"]'); - card && setTimeout(function() { - section.querySelector(".emby-scroller").toStart(card.previousSibling || card, !0) - }, 100) - }) + + if (card) { + setTimeout(function () { + section.querySelector(".emby-scroller").toStart(card.previousSibling || card, true); + }, 100); + } + }); } } function renderMoreFromArtist(view, item, apiClient) { var section = view.querySelector(".moreFromArtistSection"); + if (section) { if ("MusicArtist" === item.Type) { - if (!apiClient.isMinServerVersion("3.4.1.19")) return void section.classList.add("hide") - } else if ("MusicAlbum" !== item.Type || !item.AlbumArtists || !item.AlbumArtists.length) return void section.classList.add("hide"); + if (!apiClient.isMinServerVersion("3.4.1.19")) { + return void section.classList.add("hide"); + } + } else if ("MusicAlbum" !== item.Type || !item.AlbumArtists || !item.AlbumArtists.length) { + return void section.classList.add("hide"); + } + var query = { IncludeItemTypes: "MusicAlbum", - Recursive: !0, + Recursive: true, ExcludeItemIds: item.Id, SortBy: "ProductionYear,SortName", SortOrder: "Descending" }; - "MusicArtist" === item.Type ? query.ContributingArtistIds = item.Id : apiClient.isMinServerVersion("3.4.1.18") ? query.AlbumArtistIds = item.AlbumArtists[0].Id : query.ArtistIds = item.AlbumArtists[0].Id, apiClient.getItems(apiClient.getCurrentUserId(), query).then(function(result) { - if (!result.Items.length) return void section.classList.add("hide"); - section.classList.remove("hide"), "MusicArtist" === item.Type ? section.querySelector("h2").innerHTML = globalize.translate("HeaderAppearsOn") : section.querySelector("h2").innerHTML = globalize.translate("MoreFromValue", item.AlbumArtists[0].Name), cardBuilder.buildCards(result.Items, { + + if ("MusicArtist" === item.Type) { + query.ContributingArtistIds = item.Id; + } else if (apiClient.isMinServerVersion("3.4.1.18")) { + query.AlbumArtistIds = item.AlbumArtists[0].Id; + } else { + query.ArtistIds = item.AlbumArtists[0].Id; + } + + apiClient.getItems(apiClient.getCurrentUserId(), query).then(function (result) { + if (!result.Items.length) { + return void section.classList.add("hide"); + } + + section.classList.remove("hide"); + + if ("MusicArtist" === item.Type) { + section.querySelector("h2").innerHTML = globalize.translate("HeaderAppearsOn"); + } else { + section.querySelector("h2").innerHTML = globalize.translate("MoreFromValue", item.AlbumArtists[0].Name); + } + + cardBuilder.buildCards(result.Items, { parentContainer: section, itemsContainer: section.querySelector(".itemsContainer"), shape: "autooverflow", sectionTitleTagName: "h2", - scalable: !0, + scalable: true, coverImage: "MusicArtist" === item.Type || "MusicAlbum" === item.Type, - showTitle: !0, - showParentTitle: !1, - centerText: !0, - overlayText: !1, - overlayPlayButton: !0, - showYear: !0 - }) - }) + showTitle: true, + showParentTitle: false, + centerText: true, + overlayText: false, + overlayPlayButton: true, + showYear: true + }); + }); } } function renderSimilarItems(page, item, context) { var similarCollapsible = page.querySelector("#similarCollapsible"); + if (similarCollapsible) { - if ("Movie" != item.Type && "Trailer" != item.Type && "Series" != item.Type && "Program" != item.Type && "Recording" != item.Type && "MusicAlbum" != item.Type && "MusicArtist" != item.Type && "Playlist" != item.Type) return void similarCollapsible.classList.add("hide"); + if ("Movie" != item.Type && "Trailer" != item.Type && "Series" != item.Type && "Program" != item.Type && "Recording" != item.Type && "MusicAlbum" != item.Type && "MusicArtist" != item.Type && "Playlist" != item.Type) { + return void similarCollapsible.classList.add("hide"); + } + similarCollapsible.classList.remove("hide"); - var apiClient = connectionManager.getApiClient(item.ServerId), - options = { - userId: apiClient.getCurrentUserId(), - limit: 12, - fields: "PrimaryImageAspectRatio,UserData,CanDelete" - }; - "MusicAlbum" == item.Type && item.AlbumArtists && item.AlbumArtists.length && (options.ExcludeArtistIds = item.AlbumArtists[0].Id), apiClient.getSimilarItems(item.Id, options).then(function(result) { - if (!result.Items.length) return void similarCollapsible.classList.add("hide"); + var apiClient = connectionManager.getApiClient(item.ServerId); + var options = { + userId: apiClient.getCurrentUserId(), + limit: 12, + fields: "PrimaryImageAspectRatio,UserData,CanDelete" + }; + + if ("MusicAlbum" == item.Type && item.AlbumArtists && item.AlbumArtists.length) { + options.ExcludeArtistIds = item.AlbumArtists[0].Id; + } + + apiClient.getSimilarItems(item.Id, options).then(function (result) { + if (!result.Items.length) { + return void similarCollapsible.classList.add("hide"); + } + similarCollapsible.classList.remove("hide"); var html = ""; html += cardBuilder.getCardsHtml({ items: result.Items, shape: "autooverflow", showParentTitle: "MusicAlbum" == item.Type, - centerText: !0, - showTitle: !0, + centerText: true, + showTitle: true, context: context, - lazy: !0, - showDetailsMenu: !0, + lazy: true, + showDetailsMenu: true, coverImage: "MusicAlbum" == item.Type || "MusicArtist" == item.Type, - overlayPlayButton: !0, - overlayText: !1, + overlayPlayButton: true, + overlayText: false, showYear: "Movie" === item.Type || "Trailer" === item.Type }); var similarContent = similarCollapsible.querySelector(".similarContent"); - similarContent.innerHTML = html, imageLoader.lazyChildren(similarContent) - }) + similarContent.innerHTML = html; + imageLoader.lazyChildren(similarContent); + }); } } function renderSeriesAirTime(page, item, isStatic) { var seriesAirTime = page.querySelector("#seriesAirTime"); - if ("Series" != item.Type) return void seriesAirTime.classList.add("hide"); + if ("Series" != item.Type) { + seriesAirTime.classList.add("hide"); + return; + } var html = ""; - if (item.AirDays && item.AirDays.length && (html += 7 == item.AirDays.length ? "daily" : item.AirDays.map(function(a) { - return a + "s" - }).join(",")), item.AirTime && (html += " at " + item.AirTime), item.Studios.length) - if (isStatic) html += " on " + item.Studios[0].Name; - else { - var context = inferContext(item), - href = appRouter.getRouteUrl(item.Studios[0], { - context: context, - itemType: "Studio", - serverId: item.ServerId - }); - html += ' on ' + item.Studios[0].Name + "" - } html ? (html = ("Ended" == item.Status ? "Aired " : "Airs ") + html, seriesAirTime.innerHTML = html, seriesAirTime.classList.remove("hide")) : seriesAirTime.classList.add("hide") + if (item.AirDays && item.AirDays.length) { + if (7 == item.AirDays.length) { + html += "daily"; + } else { + html += item.AirDays.map(function (a) { + return a + "s"; + }).join(","); + } + } + if (item.AirTime) { + html += " at " + item.AirTime; + } + if (item.Studios.length) { + if (isStatic) { + html += " on " + item.Studios[0].Name; + } else { + var context = inferContext(item); + var href = appRouter.getRouteUrl(item.Studios[0], { + context: context, + itemType: "Studio", + serverId: item.ServerId + }); + html += ' on ' + item.Studios[0].Name + ""; + } + } + if (html) { + html = ("Ended" == item.Status ? "Aired " : "Airs ") + html; + seriesAirTime.innerHTML = html; + seriesAirTime.classList.remove("hide"); + } else { + seriesAirTime.classList.add("hide"); + } } function renderTags(page, item) { - var itemTags = page.querySelector(".itemTags"), - tagElements = [], - tags = item.Tags || []; - "Program" === item.Type && (tags = []); - for (var i = 0, length = tags.length; i < length; i++) tagElements.push(tags[i]); - tagElements.length ? (itemTags.innerHTML = globalize.translate("TagsValue", tagElements.join(", ")), itemTags.classList.remove("hide")) : (itemTags.innerHTML = "", itemTags.classList.add("hide")) + var itemTags = page.querySelector(".itemTags"); + var tagElements = []; + var tags = item.Tags || []; + + if ("Program" === item.Type) { + tags = []; + } + + for (var i = 0, length = tags.length; i < length; i++) { + tagElements.push(tags[i]); + } + + if (tagElements.length) { + itemTags.innerHTML = globalize.translate("TagsValue", tagElements.join(", ")); + itemTags.classList.remove("hide"); + } else { + itemTags.innerHTML = ""; + itemTags.classList.add("hide"); + } } function renderChildren(page, item) { - var fields = "ItemCounts,PrimaryImageAspectRatio,BasicSyncInfo,CanDelete,MediaSourceCount", - query = { - ParentId: item.Id, + var fields = "ItemCounts,PrimaryImageAspectRatio,BasicSyncInfo,CanDelete,MediaSourceCount"; + var query = { + ParentId: item.Id, + Fields: fields + }; + + if ("BoxSet" !== item.Type) { + query.SortBy = "SortName"; + } + + var promise; + var apiClient = connectionManager.getApiClient(item.ServerId); + var userId = apiClient.getCurrentUserId(); + + if ("Series" == item.Type) { + promise = apiClient.getSeasons(item.Id, { + userId: userId, Fields: fields - }; - "BoxSet" !== item.Type && (query.SortBy = "SortName"); - var promise, apiClient = connectionManager.getApiClient(item.ServerId), - userId = apiClient.getCurrentUserId(); - "Series" == item.Type ? promise = apiClient.getSeasons(item.Id, { - userId: userId, - Fields: fields - }) : "Season" == item.Type ? (fields += ",Overview", promise = apiClient.getEpisodes(item.SeriesId, { - seasonId: item.Id, - userId: userId, - Fields: fields - })) : "MusicAlbum" == item.Type || "MusicArtist" == item.Type && (query.SortBy = "ProductionYear,SortName"), promise = promise || apiClient.getItems(apiClient.getCurrentUserId(), query), promise.then(function(result) { - var html = "", - scrollX = !1, - isList = !1, - childrenItemsContainer = page.querySelector(".childrenItemsContainer"); - if ("MusicAlbum" == item.Type) html = listView.getListViewHtml({ - items: result.Items, - smallIcon: !0, - showIndex: !0, - index: "disc", - showIndexNumberLeft: !0, - playFromHere: !0, - action: "playallfromhere", - image: !1, - artist: "auto", - containerAlbumArtists: item.AlbumArtists, - addToListButton: !0 - }), isList = !0; - else if ("Series" == item.Type) scrollX = enableScrollX(), html = cardBuilder.getCardsHtml({ - items: result.Items, - shape: getPortraitShape(), - showTitle: !0, - centerText: !0, - lazy: !0, - overlayPlayButton: !0, - allowBottomPadding: !scrollX }); - else if ("Season" == item.Type || "Episode" == item.Type) { - if ("Episode" === item.Type || (isList = !0), scrollX = "Episode" == item.Type, result.Items.length < 2 && "Episode" === item.Type) return; - "Episode" === item.Type ? html = cardBuilder.getCardsHtml({ + } else if ("Season" == item.Type) { + fields += ",Overview"; + promise = apiClient.getEpisodes(item.SeriesId, { + seasonId: item.Id, + userId: userId, + Fields: fields + }); + } else if ("MusicArtist" == item.Type) { + query.SortBy = "ProductionYear,SortName"; + } + + promise = promise || apiClient.getItems(apiClient.getCurrentUserId(), query); + promise.then(function (result) { + var html = ""; + var scrollX = false; + var isList = false; + var childrenItemsContainer = page.querySelector(".childrenItemsContainer"); + + if ("MusicAlbum" == item.Type) { + html = listView.getListViewHtml({ items: result.Items, - shape: getThumbShape(scrollX), - showTitle: !0, - displayAsSpecial: "Season" == item.Type && item.IndexNumber, - playFromHere: !0, - overlayText: !0, - lazy: !0, - showDetailsMenu: !0, - overlayPlayButton: !0, - allowBottomPadding: !scrollX, - includeParentInfoInTitle: !1 - }) : "Season" === item.Type && (html = listView.getListViewHtml({ + smallIcon: true, + showIndex: true, + index: "disc", + showIndexNumberLeft: true, + playFromHere: true, + action: "playallfromhere", + image: false, + artist: "auto", + containerAlbumArtists: item.AlbumArtists, + addToListButton: true + }); + isList = true; + } else if ("Series" == item.Type) { + scrollX = enableScrollX(); + html = cardBuilder.getCardsHtml({ items: result.Items, - showIndexNumber: !1, - enableOverview: !0, - imageSize: "large", - enableSideMediaInfo: !1, - highlight: !1, - action: "none", - infoButton: !0, - imagePlayButton: !0, - includeParentInfoInTitle: !1 - })) + shape: getPortraitShape(), + showTitle: true, + centerText: true, + lazy: true, + overlayPlayButton: true, + allowBottomPadding: !scrollX + }); + } else if ("Season" == item.Type || "Episode" == item.Type) { + if ("Episode" !== item.Type) { + isList = true; + } + scrollX = "Episode" == item.Type; + if (result.Items.length < 2 && "Episode" === item.Type) { + return; + } + + if ("Episode" === item.Type) { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: getThumbShape(scrollX), + showTitle: true, + displayAsSpecial: "Season" == item.Type && item.IndexNumber, + playFromHere: true, + overlayText: true, + lazy: true, + showDetailsMenu: true, + overlayPlayButton: true, + allowBottomPadding: !scrollX, + includeParentInfoInTitle: false + }); + } else if ("Season" === item.Type) { + html = listView.getListViewHtml({ + items: result.Items, + showIndexNumber: false, + enableOverview: true, + imageSize: "large", + enableSideMediaInfo: false, + highlight: false, + action: layoutManager.tv ? "resume" : "none", + infoButton: true, + imagePlayButton: true, + includeParentInfoInTitle: false + }); + } } - if ("BoxSet" !== item.Type && page.querySelector("#childrenCollapsible").classList.remove("hide"), scrollX ? (childrenItemsContainer.classList.add("scrollX"), childrenItemsContainer.classList.add("hiddenScrollX"), childrenItemsContainer.classList.remove("vertical-wrap"), childrenItemsContainer.classList.remove("vertical-list")) : (childrenItemsContainer.classList.remove("scrollX"), childrenItemsContainer.classList.remove("hiddenScrollX"), childrenItemsContainer.classList.remove("smoothScrollX"), isList ? (childrenItemsContainer.classList.add("vertical-list"), childrenItemsContainer.classList.remove("vertical-wrap")) : (childrenItemsContainer.classList.add("vertical-wrap"), childrenItemsContainer.classList.remove("vertical-list"))), childrenItemsContainer.innerHTML = html, imageLoader.lazyChildren(childrenItemsContainer), "BoxSet" == item.Type) { + + if ("BoxSet" !== item.Type) { + page.querySelector("#childrenCollapsible").classList.remove("hide"); + } + if (scrollX) { + childrenItemsContainer.classList.add("scrollX"); + childrenItemsContainer.classList.add("hiddenScrollX"); + childrenItemsContainer.classList.remove("vertical-wrap"); + childrenItemsContainer.classList.remove("vertical-list"); + } else { + childrenItemsContainer.classList.remove("scrollX"); + childrenItemsContainer.classList.remove("hiddenScrollX"); + childrenItemsContainer.classList.remove("smoothScrollX"); + if (isList) { + childrenItemsContainer.classList.add("vertical-list"); + childrenItemsContainer.classList.remove("vertical-wrap"); + } else { + childrenItemsContainer.classList.add("vertical-wrap"); + childrenItemsContainer.classList.remove("vertical-list"); + } + } + childrenItemsContainer.innerHTML = html; + imageLoader.lazyChildren(childrenItemsContainer); + if ("BoxSet" == item.Type) { var collectionItemTypes = [{ name: globalize.translate("HeaderVideos"), mediaType: "Video" @@ -838,175 +1498,276 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild name: globalize.translate("HeaderBooks"), type: "Book" }]; - renderCollectionItems(page, item, collectionItemTypes, result.Items) + renderCollectionItems(page, item, collectionItemTypes, result.Items); } - }), "Season" == item.Type ? page.querySelector("#childrenTitle").innerHTML = globalize.translate("HeaderEpisodes") : "Series" == item.Type ? page.querySelector("#childrenTitle").innerHTML = globalize.translate("HeaderSeasons") : "MusicAlbum" == item.Type ? page.querySelector("#childrenTitle").innerHTML = globalize.translate("HeaderTracks") : page.querySelector("#childrenTitle").innerHTML = globalize.translate("HeaderItems"), "MusicAlbum" == item.Type || "Season" == item.Type ? (page.querySelector(".childrenSectionHeader").classList.add("hide"), page.querySelector("#childrenCollapsible").classList.add("verticalSection-extrabottompadding")) : page.querySelector(".childrenSectionHeader").classList.remove("hide") + }); + + if ("Season" == item.Type) { + page.querySelector("#childrenTitle").innerHTML = globalize.translate("HeaderEpisodes"); + } else if ("Series" == item.Type) { + page.querySelector("#childrenTitle").innerHTML = globalize.translate("HeaderSeasons"); + } else if ("MusicAlbum" == item.Type) { + page.querySelector("#childrenTitle").innerHTML = globalize.translate("HeaderTracks"); + } else { + page.querySelector("#childrenTitle").innerHTML = globalize.translate("HeaderItems"); + } + + if ("MusicAlbum" == item.Type || "Season" == item.Type) { + page.querySelector(".childrenSectionHeader").classList.add("hide"); + page.querySelector("#childrenCollapsible").classList.add("verticalSection-extrabottompadding"); + } else { + page.querySelector(".childrenSectionHeader").classList.remove("hide"); + } } function renderItemsByName(page, item, user) { - require("scripts/itembynamedetailpage".split(","), function() { - window.ItemsByName.renderItems(page, item) - }) + require("scripts/itembynamedetailpage".split(","), function () { + window.ItemsByName.renderItems(page, item); + }); } function renderPlaylistItems(page, item, user) { - require("scripts/playlistedit".split(","), function() { - PlaylistViewer.render(page, item) - }) + require("scripts/playlistedit".split(","), function () { + PlaylistViewer.render(page, item); + }); } function renderProgramsForChannel(page, result) { - for (var html = "", currentItems = [], currentStartDate = null, i = 0, length = result.Items.length; i < length; i++) { - var item = result.Items[i], - itemStartDate = datetime.parseISO8601Date(item.StartDate); - currentStartDate && currentStartDate.toDateString() === itemStartDate.toDateString() || (currentItems.length && (html += '
            ', html += '

            ' + datetime.toLocaleDateString(currentStartDate, { + var html = ""; + var currentItems = []; + var currentStartDate = null; + + for (var i = 0, length = result.Items.length; i < length; i++) { + var item = result.Items[i]; + var itemStartDate = datetime.parseISO8601Date(item.StartDate); + + if (!(currentStartDate && currentStartDate.toDateString() === itemStartDate.toDateString())) { + if (currentItems.length) { + html += '
            '; + html += '

            ' + datetime.toLocaleDateString(currentStartDate, { + weekday: "long", + month: "long", + day: "numeric" + }) + "

            "; + html += '
            ' + listView.getListViewHtml({ + items: currentItems, + enableUserDataButtons: false, + showParentTitle: true, + image: false, + showProgramTime: true, + mediaInfo: false, + parentTitleWithTitle: true + }) + "
            "; + } + + currentStartDate = itemStartDate; + currentItems = []; + } + + currentItems.push(item); + } + + if (currentItems.length) { + html += '
            '; + html += '

            ' + datetime.toLocaleDateString(currentStartDate, { weekday: "long", month: "long", day: "numeric" - }) + "

            ", html += '
            ' + listView.getListViewHtml({ + }) + "

            "; + html += '
            ' + listView.getListViewHtml({ items: currentItems, - enableUserDataButtons: !1, - showParentTitle: !0, - image: !1, - showProgramTime: !0, - mediaInfo: !1, - parentTitleWithTitle: !0 - }) + "
            "), currentStartDate = itemStartDate, currentItems = []), currentItems.push(item) + enableUserDataButtons: false, + showParentTitle: true, + image: false, + showProgramTime: true, + mediaInfo: false, + parentTitleWithTitle: true + }) + "
            "; } - currentItems.length && (html += '
            ', html += '

            ' + datetime.toLocaleDateString(currentStartDate, { - weekday: "long", - month: "long", - day: "numeric" - }) + "

            ", html += '
            ' + listView.getListViewHtml({ - items: currentItems, - enableUserDataButtons: !1, - showParentTitle: !0, - image: !1, - showProgramTime: !0, - mediaInfo: !1, - parentTitleWithTitle: !0 - }) + "
            "), page.querySelector(".programGuide").innerHTML = html + + page.querySelector(".programGuide").innerHTML = html; } function renderChannelGuide(page, apiClient, item) { - "TvChannel" === item.Type && (page.querySelector(".programGuideSection").classList.remove("hide"), apiClient.getLiveTvPrograms({ - ChannelIds: item.Id, - UserId: apiClient.getCurrentUserId(), - HasAired: !1, - SortBy: "StartDate", - EnableTotalRecordCount: !1, - EnableImages: !1, - ImageTypeLimit: 0, - EnableUserData: !1 - }).then(function(result) { - renderProgramsForChannel(page, result) - })) + if ("TvChannel" === item.Type) { + page.querySelector(".programGuideSection").classList.remove("hide"); + apiClient.getLiveTvPrograms({ + ChannelIds: item.Id, + UserId: apiClient.getCurrentUserId(), + HasAired: false, + SortBy: "StartDate", + EnableTotalRecordCount: false, + EnableImages: false, + ImageTypeLimit: 0, + EnableUserData: false + }).then(function (result) { + renderProgramsForChannel(page, result); + }); + } } function renderSeriesSchedule(page, item, user) { var apiClient = connectionManager.getApiClient(item.ServerId); apiClient.getLiveTvPrograms({ UserId: apiClient.getCurrentUserId(), - HasAired: !1, + HasAired: false, SortBy: "StartDate", - EnableTotalRecordCount: !1, - EnableImages: !1, + EnableTotalRecordCount: false, + EnableImages: false, ImageTypeLimit: 0, Limit: 50, - EnableUserData: !1, + EnableUserData: false, LibrarySeriesId: item.Id - }).then(function(result) { - result.Items.length ? page.querySelector("#seriesScheduleSection").classList.remove("hide") : page.querySelector("#seriesScheduleSection").classList.add("hide"), page.querySelector("#seriesScheduleList").innerHTML = listView.getListViewHtml({ + }).then(function (result) { + if (result.Items.length) { + page.querySelector("#seriesScheduleSection").classList.remove("hide"); + } else { + page.querySelector("#seriesScheduleSection").classList.add("hide"); + } + + page.querySelector("#seriesScheduleList").innerHTML = listView.getListViewHtml({ items: result.Items, - enableUserDataButtons: !1, - showParentTitle: !1, - image: !1, - showProgramDateTime: !0, - mediaInfo: !1, - showTitle: !0, - moreButton: !1, + enableUserDataButtons: false, + showParentTitle: false, + image: false, + showProgramDateTime: true, + mediaInfo: false, + showTitle: true, + moreButton: false, action: "programdialog" - }), loading.hide() - }) + }); + loading.hide(); + }); } function inferContext(item) { - return "Movie" === item.Type || "BoxSet" === item.Type ? "movies" : "Series" === item.Type || "Season" === item.Type || "Episode" === item.Type ? "tvshows" : "MusicArtist" === item.Type || "MusicAlbum" === item.Type || "Audio" === item.Type || "AudioBook" === item.Type ? "music" : "Program" === item.Type ? "livetv" : null + if ("Movie" === item.Type || "BoxSet" === item.Type) { + return "movies"; + } + + if ("Series" === item.Type || "Season" === item.Type || "Episode" === item.Type) { + return "tvshows"; + } + + if ("MusicArtist" === item.Type || "MusicAlbum" === item.Type || "Audio" === item.Type || "AudioBook" === item.Type) { + return "music"; + } + + if ("Program" === item.Type) { + return "livetv"; + } + + return null; } function filterItemsByCollectionItemType(items, typeInfo) { - return items.filter(function(item) { - return typeInfo.mediaType ? item.MediaType == typeInfo.mediaType : item.Type == typeInfo.type - }) + return items.filter(function (item) { + if (typeInfo.mediaType) { + return item.MediaType == typeInfo.mediaType; + } + + return item.Type == typeInfo.type; + }); } function canPlaySomeItemInCollection(items) { var i = 0; + for (length = items.length; i < length; i++) { if (playbackManager.canPlay(items[i])) { return true; } } + return false; } function renderCollectionItems(page, parentItem, types, items) { page.querySelector(".collectionItems").innerHTML = ""; - var i, length; + var i; + var length; + for (i = 0, length = types.length; i < length; i++) { - var type = types[i], - typeItems = filterItemsByCollectionItemType(items, type); - typeItems.length && renderCollectionItemType(page, parentItem, type, typeItems) + var type = types[i]; + var typeItems = filterItemsByCollectionItemType(items, type); + + if (typeItems.length) { + renderCollectionItemType(page, parentItem, type, typeItems); + } } + var otherType = { - name: globalize.translate("HeaderOtherItems") - }, - otherTypeItems = items.filter(function(curr) { - return !types.filter(function(t) { - return filterItemsByCollectionItemType([curr], t).length > 0 - }).length - }); - otherTypeItems.length && renderCollectionItemType(page, parentItem, otherType, otherTypeItems), items.length || renderCollectionItemType(page, parentItem, { - name: globalize.translate("HeaderItems") - }, items); - var containers = page.querySelectorAll(".collectionItemsContainer"), - notifyRefreshNeeded = function() { - renderChildren(page, parentItem) - }; - for (i = 0, length = containers.length; i < length; i++) containers[i].notifyRefreshNeeded = notifyRefreshNeeded + name: globalize.translate("HeaderOtherItems") + }; + var otherTypeItems = items.filter(function (curr) { + return !types.filter(function (t) { + return filterItemsByCollectionItemType([curr], t).length > 0; + }).length; + }); + + if (otherTypeItems.length) { + renderCollectionItemType(page, parentItem, otherType, otherTypeItems); + } + + if (!items.length) { + renderCollectionItemType(page, parentItem, { + name: globalize.translate("HeaderItems") + }, items); + } + + var containers = page.querySelectorAll(".collectionItemsContainer"); + + var notifyRefreshNeeded = function () { + renderChildren(page, parentItem); + }; + + for (i = 0, length = containers.length; i < length; i++) { + containers[i].notifyRefreshNeeded = notifyRefreshNeeded; + } // if nothing in the collection can be played hide play and shuffle buttons if (!canPlaySomeItemInCollection(items)) { hideAll(page, "btnPlay", false); hideAll(page, "btnShuffle", false); - } + } } function renderCollectionItemType(page, parentItem, type, items) { var html = ""; - html += '
            ', html += '
            ', html += '

            ', html += "" + type.name + "", html += "

            ", html += '', html += "
            ", html += '
            '; - var shape = "MusicAlbum" == type.type ? getSquareShape(!1) : getPortraitShape(!1); + html += '
            '; + html += '
            '; + html += '

            '; + html += "" + type.name + ""; + html += "

            "; + html += ''; + html += "
            "; + html += '
            '; + var shape = "MusicAlbum" == type.type ? getSquareShape(false) : getPortraitShape(false); html += cardBuilder.getCardsHtml({ items: items, shape: shape, - showTitle: !0, - centerText: !0, - lazy: !0, - showDetailsMenu: !0, - overlayMoreButton: !0, - showAddToCollection: !1, - showRemoveFromCollection: !0, + showTitle: true, + centerText: true, + lazy: true, + showDetailsMenu: true, + overlayMoreButton: true, + showAddToCollection: false, + showRemoveFromCollection: true, collectionId: parentItem.Id - }), html += "
            ", html += "
            "; + }); + html += "
            "; + html += "
            "; var collectionItems = page.querySelector(".collectionItems"); - collectionItems.insertAdjacentHTML("beforeend", html), imageLoader.lazyChildren(collectionItems), collectionItems.querySelector(".btnAddToCollection").addEventListener("click", function() { - require(["alert"], function(alert) { + collectionItems.insertAdjacentHTML("beforeend", html); + imageLoader.lazyChildren(collectionItems); + collectionItems.querySelector(".btnAddToCollection").addEventListener("click", function () { + require(["alert"], function (alert) { alert({ text: globalize.translate("AddItemToCollectionHelp"), html: globalize.translate("AddItemToCollectionHelp") + '

            ' + globalize.translate("ButtonLearnMore") + "" - }) - }) - }) + }); + }); + }); } function renderMusicVideos(page, item, user) { @@ -1014,295 +1775,362 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild SortBy: "SortName", SortOrder: "Ascending", IncludeItemTypes: "MusicVideo", - Recursive: !0, + Recursive: true, Fields: "PrimaryImageAspectRatio,BasicSyncInfo,CanDelete,MediaSourceCount", AlbumIds: item.Id - }).then(function(result) { + }).then(function (result) { if (result.Items.length) { page.querySelector("#musicVideosCollapsible").classList.remove("hide"); var musicVideosContent = page.querySelector(".musicVideosContent"); - musicVideosContent.innerHTML = getVideosHtml(result.Items, user), imageLoader.lazyChildren(musicVideosContent) - } else page.querySelector("#musicVideosCollapsible").classList.add("hide") - }) + musicVideosContent.innerHTML = getVideosHtml(result.Items, user); + imageLoader.lazyChildren(musicVideosContent); + } else { + page.querySelector("#musicVideosCollapsible").classList.add("hide"); + } + }); } function renderAdditionalParts(page, item, user) { - connectionManager.getApiClient(item.ServerId).getAdditionalVideoParts(user.Id, item.Id).then(function(result) { + connectionManager.getApiClient(item.ServerId).getAdditionalVideoParts(user.Id, item.Id).then(function (result) { if (result.Items.length) { page.querySelector("#additionalPartsCollapsible").classList.remove("hide"); var additionalPartsContent = page.querySelector("#additionalPartsContent"); - additionalPartsContent.innerHTML = getVideosHtml(result.Items, user), imageLoader.lazyChildren(additionalPartsContent) - } else page.querySelector("#additionalPartsCollapsible").classList.add("hide") - }) + additionalPartsContent.innerHTML = getVideosHtml(result.Items, user); + imageLoader.lazyChildren(additionalPartsContent); + } else { + page.querySelector("#additionalPartsCollapsible").classList.add("hide"); + } + }); } function renderScenes(page, item) { var chapters = item.Chapters || []; + if (chapters.length && !chapters[0].ImageTag && (chapters = []), chapters.length) { page.querySelector("#scenesCollapsible").classList.remove("hide"); var scenesContent = page.querySelector("#scenesContent"); - require(["chaptercardbuilder"], function(chaptercardbuilder) { + + require(["chaptercardbuilder"], function (chaptercardbuilder) { chaptercardbuilder.buildChapterCards(item, chapters, { itemsContainer: scenesContent, width: 400, backdropShape: "overflowBackdrop", squareShape: "overflowSquare" - }) - }) - } else page.querySelector("#scenesCollapsible").classList.add("hide") + }); + }); + } else { + page.querySelector("#scenesCollapsible").classList.add("hide"); + } } function getVideosHtml(items, user, limit, moreButtonClass) { var html = cardBuilder.getCardsHtml({ items: items, shape: "auto", - showTitle: !0, + showTitle: true, action: "play", - overlayText: !1, - centerText: !0, - showRuntime: !0 + overlayText: false, + centerText: true, + showRuntime: true }); - return limit && items.length > limit && (html += '

            "), html + + if (limit && items.length > limit) { + html += '

            "; + } + + return html; } function renderSpecials(page, item, user, limit) { - connectionManager.getApiClient(item.ServerId).getSpecialFeatures(user.Id, item.Id).then(function(specials) { + connectionManager.getApiClient(item.ServerId).getSpecialFeatures(user.Id, item.Id).then(function (specials) { var specialsContent = page.querySelector("#specialsContent"); - specialsContent.innerHTML = getVideosHtml(specials, user, limit, "moreSpecials"), imageLoader.lazyChildren(specialsContent) - }) + specialsContent.innerHTML = getVideosHtml(specials, user, limit, "moreSpecials"); + imageLoader.lazyChildren(specialsContent); + }); } function renderCast(page, item, context, limit, isStatic) { - var people = (item.People || []).filter(function(p) { - return "Director" !== p.Type + var people = (item.People || []).filter(function (p) { + return "Director" !== p.Type; }); - if (!people.length) return void page.querySelector("#castCollapsible").classList.add("hide"); + + if (!people.length) { + return void page.querySelector("#castCollapsible").classList.add("hide"); + } + page.querySelector("#castCollapsible").classList.remove("hide"); var castContent = page.querySelector("#castContent"); - require(["peoplecardbuilder"], function(peoplecardbuilder) { + + require(["peoplecardbuilder"], function (peoplecardbuilder) { peoplecardbuilder.buildPeopleCards(people, { itemsContainer: castContent, - coverImage: !0, + coverImage: true, serverId: item.ServerId, width: 160, shape: getPortraitShape() - }) - }) + }); + }); } function itemDetailPage() { var self = this; - self.setInitialCollapsibleState = setInitialCollapsibleState, self.renderDetails = renderDetails, self.renderCast = renderCast + self.setInitialCollapsibleState = setInitialCollapsibleState; + self.renderDetails = renderDetails; + self.renderCast = renderCast; } function bindAll(view, selector, eventName, fn) { - var i, length, elems = view.querySelectorAll(selector); - for (i = 0, length = elems.length; i < length; i++) elems[i].addEventListener(eventName, fn) + var i; + var length; + var elems = view.querySelectorAll(selector); + + for (i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener(eventName, fn); + } } function onTrackSelectionsSubmit(e) { - return e.preventDefault(), !1 + e.preventDefault(); + return false; } - return window.ItemDetailPage = new itemDetailPage, - function(view, params) { - function reload(instance, page, params) { - loading.show(); - var apiClient = params.serverId ? connectionManager.getApiClient(params.serverId) : ApiClient, - promises = [getPromise(apiClient, params), apiClient.getCurrentUser()]; - Promise.all(promises).then(function(responses) { - var item = responses[0], - user = responses[1]; - currentItem = item, reloadFromItem(instance, page, params, item, user) - }) - } - function splitVersions(instance, page, apiClient, params) { - require(["confirm"], function(confirm) { - confirm("Are you sure you wish to split the media sources into separate items?", "Split Media Apart").then(function() { - loading.show(), apiClient.ajax({ - type: "DELETE", - url: apiClient.getUrl("Videos/" + params.id + "/AlternateSources") - }).then(function() { - loading.hide(), reload(instance, page, params) - }) - }) - }) - } + window.ItemDetailPage = new itemDetailPage(); + return function (view, params) { + function reload(instance, page, params) { + loading.show(); + var apiClient = params.serverId ? connectionManager.getApiClient(params.serverId) : ApiClient; + var promises = [getPromise(apiClient, params), apiClient.getCurrentUser()]; + Promise.all(promises).then(function (responses) { + var item = responses[0]; + var user = responses[1]; + currentItem = item; + reloadFromItem(instance, page, params, item, user); + }); + } - function getPlayOptions(startPosition) { - var audioStreamIndex = view.querySelector(".selectAudio").value || null; - return { - startPositionTicks: startPosition, - mediaSourceId: view.querySelector(".selectSource").value, - audioStreamIndex: audioStreamIndex, - subtitleStreamIndex: view.querySelector(".selectSubtitles").value - } - } + function splitVersions(instance, page, apiClient, params) { + require(["confirm"], function (confirm) { + confirm("Are you sure you wish to split the media sources into separate items?", "Split Media Apart").then(function () { + loading.show(); + apiClient.ajax({ + type: "DELETE", + url: apiClient.getUrl("Videos/" + params.id + "/AlternateSources") + }).then(function () { + loading.hide(); + reload(instance, page, params); + }); + }); + }); + } - function playItem(item, startPosition) { - var playOptions = getPlayOptions(startPosition); - playOptions.items = [item], playbackManager.play(playOptions) - } + function getPlayOptions(startPosition) { + var audioStreamIndex = view.querySelector(".selectAudio").value || null; + return { + startPositionTicks: startPosition, + mediaSourceId: view.querySelector(".selectSource").value, + audioStreamIndex: audioStreamIndex, + subtitleStreamIndex: view.querySelector(".selectSubtitles").value + }; + } - function playTrailer(page) { - playbackManager.playTrailers(currentItem) - } + function playItem(item, startPosition) { + var playOptions = getPlayOptions(startPosition); + playOptions.items = [item]; + playbackManager.play(playOptions); + } - function playCurrentItem(button, mode) { - var item = currentItem; - if ("Program" === item.Type) { - var apiClient = connectionManager.getApiClient(item.ServerId); - return void apiClient.getLiveTvChannel(item.ChannelId, apiClient.getCurrentUserId()).then(function(channel) { - playbackManager.play({ - items: [channel] - }) - }) - } - playItem(item, item.UserData && "resume" === mode ? item.UserData.PlaybackPositionTicks : 0) - } + function playTrailer(page) { + playbackManager.playTrailers(currentItem); + } - function onPlayClick() { - playCurrentItem(this, this.getAttribute("data-mode")) - } + function playCurrentItem(button, mode) { + var item = currentItem; - function onInstantMixClick() { - playbackManager.instantMix(currentItem) - } - - function onShuffleClick() { - playbackManager.shuffle(currentItem) - } - - function onDeleteClick() { - require(["deleteHelper"], function(deleteHelper) { - deleteHelper.deleteItem({ - item: currentItem, - navigate: !0 - }) - }) - } - - function onCancelSeriesTimerClick() { - require(["recordingHelper"], function(recordingHelper) { - recordingHelper.cancelSeriesTimerWithConfirmation(currentItem.Id, currentItem.ServerId).then(function() { - Dashboard.navigate("livetv.html") - }) - }) - } - - function onCancelTimerClick() { - require(["recordingHelper"], function(recordingHelper) { - recordingHelper.cancelTimer(connectionManager.getApiClient(currentItem.ServerId), currentItem.TimerId).then(function() { - reload(self, view, params) - }) - }) - } - - function onPlayTrailerClick() { - playTrailer(view) - } - - function onDownloadChange() { - reload(self, view, params) - } - - function onDownloadClick() { - require(['fileDownloader'], function (fileDownloader) { - var downloadHref = apiClient.getItemDownloadUrl(currentItem.Id); - fileDownloader.download([{ - url: downloadHref, - itemId: currentItem.Id, - serverId: currentItem.serverId - }]); + if ("Program" === item.Type) { + var apiClient = connectionManager.getApiClient(item.ServerId); + return void apiClient.getLiveTvChannel(item.ChannelId, apiClient.getCurrentUserId()).then(function (channel) { + playbackManager.play({ + items: [channel] + }); }); } - function onMoreCommandsClick() { - var button = this; - apiClient.getCurrentUser().then(function(user) { - itemContextMenu.show(getContextMenuOptions(currentItem, user, button)).then(function(result) { - result.deleted ? appRouter.goHome() : result.updated && reload(self, view, params) - }) - }) - } + playItem(item, item.UserData && "resume" === mode ? item.UserData.PlaybackPositionTicks : 0); + } - function onPlayerChange() { - renderTrackSelections(view, self, currentItem), setTrailerButtonVisibility(view, currentItem) - } + function onPlayClick() { + playCurrentItem(this, this.getAttribute("data-mode")); + } - function editImages() { - return new Promise(function(resolve, reject) { - require(["imageEditor"], function(imageEditor) { - imageEditor.show({ - itemId: currentItem.Id, - serverId: currentItem.ServerId - }).then(resolve, reject) - }) - }) - } + function onInstantMixClick() { + playbackManager.instantMix(currentItem); + } - function onWebSocketMessage(e, data) { - var msg = data; - if ("UserDataChanged" === msg.MessageType && currentItem && msg.Data.UserId == apiClient.getCurrentUserId()) { - var key = currentItem.UserData.Key, - userData = msg.Data.UserDataList.filter(function(u) { - return u.Key == key - })[0]; - userData && (currentItem.UserData = userData, reloadPlayButtons(view, currentItem), apiClient.getCurrentUser().then(function(user) { - refreshImage(view, currentItem, user) - })) + function onShuffleClick() { + playbackManager.shuffle(currentItem); + } + + function onDeleteClick() { + require(["deleteHelper"], function (deleteHelper) { + deleteHelper.deleteItem({ + item: currentItem, + navigate: true + }); + }); + } + + function onCancelSeriesTimerClick() { + require(["recordingHelper"], function (recordingHelper) { + recordingHelper.cancelSeriesTimerWithConfirmation(currentItem.Id, currentItem.ServerId).then(function () { + Dashboard.navigate("livetv.html"); + }); + }); + } + + function onCancelTimerClick() { + require(["recordingHelper"], function (recordingHelper) { + recordingHelper.cancelTimer(connectionManager.getApiClient(currentItem.ServerId), currentItem.TimerId).then(function () { + reload(self, view, params); + }); + }); + } + + function onPlayTrailerClick() { + playTrailer(view); + } + + function onDownloadChange() { + reload(self, view, params); + } + + function onDownloadClick() { + require(['fileDownloader'], function (fileDownloader) { + var downloadHref = apiClient.getItemDownloadUrl(currentItem.Id); + fileDownloader.download([{ + url: downloadHref, + itemId: currentItem.Id, + serverId: currentItem.serverId + }]); + }); + } + + function onMoreCommandsClick() { + var button = this; + apiClient.getCurrentUser().then(function (user) { + itemContextMenu.show(getContextMenuOptions(currentItem, user, button)).then(function (result) { + if (result.deleted) { + appRouter.goHome(); + } else if (result.updated) { + reload(self, view, params); + } + }); + }); + } + + function onPlayerChange() { + renderTrackSelections(view, self, currentItem); + setTrailerButtonVisibility(view, currentItem); + } + + function editImages() { + return new Promise(function (resolve, reject) { + require(["imageEditor"], function (imageEditor) { + imageEditor.show({ + itemId: currentItem.Id, + serverId: currentItem.ServerId + }).then(resolve, reject); + }); + }); + } + + function onWebSocketMessage(e, data) { + var msg = data; + + if ("UserDataChanged" === msg.MessageType && currentItem && msg.Data.UserId == apiClient.getCurrentUserId()) { + var key = currentItem.UserData.Key; + var userData = msg.Data.UserDataList.filter(function (u) { + return u.Key == key; + })[0]; + + if (userData) { + currentItem.UserData = userData; + reloadPlayButtons(view, currentItem); + apiClient.getCurrentUser().then(function (user) { + refreshImage(view, currentItem, user); + }); } } - - var currentItem; - var self = this; - var apiClient = params.serverId ? connectionManager.getApiClient(params.serverId) : ApiClient; - view.querySelectorAll(".btnPlay"); - bindAll(view, ".btnPlay", "click", onPlayClick); - bindAll(view, ".btnResume", "click", onPlayClick); - bindAll(view, ".btnInstantMix", "click", onInstantMixClick); - bindAll(view, ".btnShuffle", "click", onShuffleClick); - bindAll(view, ".btnPlayTrailer", "click", onPlayTrailerClick); - bindAll(view, ".btnCancelSeriesTimer", "click", onCancelSeriesTimerClick); - bindAll(view, ".btnCancelTimer", "click", onCancelTimerClick); - bindAll(view, ".btnDeleteItem", "click", onDeleteClick); - bindAll(view, ".btnDownload", "click", onDownloadClick); - view.querySelector(".btnMoreCommands i").innerHTML = ""; - view.querySelector(".trackSelections").addEventListener("submit", onTrackSelectionsSubmit); - view.querySelector(".btnSplitVersions").addEventListener("click", function() { - splitVersions(self, view, apiClient, params) - }); - bindAll(view, ".btnMoreCommands", "click", onMoreCommandsClick); - view.querySelector(".selectSource").addEventListener("change", function() { - renderVideoSelections(view, self._currentPlaybackMediaSources); - renderAudioSelections(view, self._currentPlaybackMediaSources); - renderSubtitleSelections(view, self._currentPlaybackMediaSources); - }); - view.addEventListener("click", function(e) { - dom.parentWithClass(e.target, "moreScenes") ? apiClient.getCurrentUser().then(function(user) { - renderScenes(view, currentItem) - }) : dom.parentWithClass(e.target, "morePeople") ? renderCast(view, currentItem, params.context) : dom.parentWithClass(e.target, "moreSpecials") && apiClient.getCurrentUser().then(function(user) { - renderSpecials(view, currentItem, user) - }) - }); - view.querySelector(".detailImageContainer").addEventListener("click", function(e) { - dom.parentWithClass(e.target, "itemDetailGalleryLink") && editImages().then(function() { - reload(self, view, params) - }) - }); - view.addEventListener("viewshow", function(e) { - var page = this; - libraryMenu.setTransparentMenu(!0), e.detail.isRestored ? currentItem && (setTitle(currentItem, connectionManager.getApiClient(currentItem.ServerId)), renderTrackSelections(page, self, currentItem, !0)) : reload(self, page, params), events.on(apiClient, "message", onWebSocketMessage), events.on(playbackManager, "playerchange", onPlayerChange) - }); - view.addEventListener("viewbeforehide", function() { - events.off(apiClient, "message", onWebSocketMessage); - events.off(playbackManager, "playerchange", onPlayerChange); - libraryMenu.setTransparentMenu(false); - }); - view.addEventListener("viewdestroy", function() { - currentItem = null; - self._currentPlaybackMediaSources = null; - self.currentRecordingFields = null; - }) } + + var currentItem; + var self = this; + var apiClient = params.serverId ? connectionManager.getApiClient(params.serverId) : ApiClient; + view.querySelectorAll(".btnPlay"); + bindAll(view, ".btnPlay", "click", onPlayClick); + bindAll(view, ".btnResume", "click", onPlayClick); + bindAll(view, ".btnInstantMix", "click", onInstantMixClick); + bindAll(view, ".btnShuffle", "click", onShuffleClick); + bindAll(view, ".btnPlayTrailer", "click", onPlayTrailerClick); + bindAll(view, ".btnCancelSeriesTimer", "click", onCancelSeriesTimerClick); + bindAll(view, ".btnCancelTimer", "click", onCancelTimerClick); + bindAll(view, ".btnDeleteItem", "click", onDeleteClick); + bindAll(view, ".btnDownload", "click", onDownloadClick); + view.querySelector(".btnMoreCommands i").innerHTML = ""; + view.querySelector(".trackSelections").addEventListener("submit", onTrackSelectionsSubmit); + view.querySelector(".btnSplitVersions").addEventListener("click", function () { + splitVersions(self, view, apiClient, params); + }); + bindAll(view, ".btnMoreCommands", "click", onMoreCommandsClick); + view.querySelector(".selectSource").addEventListener("change", function () { + renderVideoSelections(view, self._currentPlaybackMediaSources); + renderAudioSelections(view, self._currentPlaybackMediaSources); + renderSubtitleSelections(view, self._currentPlaybackMediaSources); + }); + view.addEventListener("click", function (e) { + if (dom.parentWithClass(e.target, "moreScenes")) { + apiClient.getCurrentUser().then(function (user) { + renderScenes(view, currentItem); + }); + } else if (dom.parentWithClass(e.target, "morePeople")) { + renderCast(view, currentItem, params.context); + } else if (dom.parentWithClass(e.target, "moreSpecials")) { + apiClient.getCurrentUser().then(function (user) { + renderSpecials(view, currentItem, user); + }); + } + }); + view.querySelector(".detailImageContainer").addEventListener("click", function (e) { + if (dom.parentWithClass(e.target, "itemDetailGalleryLink")) { + editImages().then(function () { + reload(self, view, params); + }); + } + }); + view.addEventListener("viewshow", function (e) { + var page = this; + libraryMenu.setTransparentMenu(true); + + if (e.detail.isRestored) { + if (currentItem) { + setTitle(currentItem, connectionManager.getApiClient(currentItem.ServerId)); + renderTrackSelections(page, self, currentItem, true); + } + } else { + reload(self, page, params); + } + + events.on(apiClient, "message", onWebSocketMessage); + events.on(playbackManager, "playerchange", onPlayerChange); + }); + view.addEventListener("viewbeforehide", function () { + events.off(apiClient, "message", onWebSocketMessage); + events.off(playbackManager, "playerchange", onPlayerChange); + libraryMenu.setTransparentMenu(false); + }); + view.addEventListener("viewdestroy", function () { + currentItem = null; + self._currentPlaybackMediaSources = null; + self.currentRecordingFields = null; + }); + }; }); diff --git a/src/controllers/list.js b/src/controllers/list.js index aac1818592..d15ebd2444 100644 --- a/src/controllers/list.js +++ b/src/controllers/list.js @@ -1,4 +1,4 @@ -define(["globalize", "listView", "layoutManager", "userSettings", "focusManager", "cardBuilder", "loading", "connectionManager", "alphaNumericShortcuts", "scroller", "playbackManager", "alphaPicker", "emby-itemscontainer", "emby-scroller"], function(globalize, listView, layoutManager, userSettings, focusManager, cardBuilder, loading, connectionManager, AlphaNumericShortcuts, scroller, playbackManager, alphaPicker) { +define(["globalize", "listView", "layoutManager", "userSettings", "focusManager", "cardBuilder", "loading", "connectionManager", "alphaNumericShortcuts", "scroller", "playbackManager", "alphaPicker", "emby-itemscontainer", "emby-scroller"], function (globalize, listView, layoutManager, userSettings, focusManager, cardBuilder, loading, connectionManager, AlphaNumericShortcuts, scroller, playbackManager, alphaPicker) { "use strict"; function getInitialLiveTvQuery(instance, params) { @@ -8,83 +8,303 @@ define(["globalize", "listView", "layoutManager", "userSettings", "focusManager" Fields: "ChannelInfo,PrimaryImageAspectRatio", Limit: 300 }; - return "Recordings" === params.type ? query.IsInProgress = !1 : query.HasAired = !1, params.genreId && (query.GenreIds = params.genreId), "true" === params.IsMovie ? query.IsMovie = !0 : "false" === params.IsMovie && (query.IsMovie = !1), "true" === params.IsSeries ? query.IsSeries = !0 : "false" === params.IsSeries && (query.IsSeries = !1), "true" === params.IsNews ? query.IsNews = !0 : "false" === params.IsNews && (query.IsNews = !1), "true" === params.IsSports ? query.IsSports = !0 : "false" === params.IsSports && (query.IsSports = !1), "true" === params.IsKids ? query.IsKids = !0 : "false" === params.IsKids && (query.IsKids = !1), "true" === params.IsAiring ? query.IsAiring = !0 : "false" === params.IsAiring && (query.IsAiring = !1), modifyQueryWithFilters(instance, query) + + if ("Recordings" === params.type) { + query.IsInProgress = false; + } else { + query.HasAired = false; + } + + if (params.genreId) { + query.GenreIds = params.genreId; + } + + if ("true" === params.IsMovie) { + query.IsMovie = true; + } else if ("false" === params.IsMovie) { + query.IsMovie = false; + } + + if ("true" === params.IsSeries) { + query.IsSeries = true; + } else if ("false" === params.IsSeries) { + query.IsSeries = false; + } + + if ("true" === params.IsNews) { + query.IsNews = true; + } else if ("false" === params.IsNews) { + query.IsNews = false; + } + + if ("true" === params.IsSports) { + query.IsSports = true; + } else if ("false" === params.IsSports) { + query.IsSports = false; + } + + if ("true" === params.IsKids) { + query.IsKids = true; + } else if ("false" === params.IsKids) { + query.IsKids = false; + } + + if ("true" === params.IsAiring) { + query.IsAiring = true; + } else if ("false" === params.IsAiring) { + query.IsAiring = false; + } + + return modifyQueryWithFilters(instance, query); } function modifyQueryWithFilters(instance, query) { var sortValues = instance.getSortValues(); - query.SortBy || (query.SortBy = sortValues.sortBy, query.SortOrder = sortValues.sortOrder), query.Fields = query.Fields ? query.Fields + ",PrimaryImageAspectRatio" : "PrimaryImageAspectRatio", query.ImageTypeLimit = 1; - var hasFilters, queryFilters = [], - filters = instance.getFilters(); - return filters.IsPlayed && (queryFilters.push("IsPlayed"), hasFilters = !0), filters.IsUnplayed && (queryFilters.push("IsUnplayed"), hasFilters = !0), filters.IsFavorite && (queryFilters.push("IsFavorite"), hasFilters = !0), filters.IsResumable && (queryFilters.push("IsResumable"), hasFilters = !0), filters.VideoTypes && (hasFilters = !0, query.VideoTypes = filters.VideoTypes), filters.GenreIds && (hasFilters = !0, query.GenreIds = filters.GenreIds), filters.Is4K && (query.Is4K = !0, hasFilters = !0), filters.IsHD && (query.IsHD = !0, hasFilters = !0), filters.IsSD && (query.IsHD = !1, hasFilters = !0), filters.Is3D && (query.Is3D = !0, hasFilters = !0), filters.HasSubtitles && (query.HasSubtitles = !0, hasFilters = !0), filters.HasTrailer && (query.HasTrailer = !0, hasFilters = !0), filters.HasSpecialFeature && (query.HasSpecialFeature = !0, hasFilters = !0), filters.HasThemeSong && (query.HasThemeSong = !0, hasFilters = !0), filters.HasThemeVideo && (query.HasThemeVideo = !0, hasFilters = !0), query.Filters = queryFilters.length ? queryFilters.join(",") : null, instance.setFilterStatus(hasFilters), instance.alphaPicker && (query.NameStartsWithOrGreater = instance.alphaPicker.value()), query + + if (!query.SortBy) { + query.SortBy = sortValues.sortBy; + query.SortOrder = sortValues.sortOrder; + } + + query.Fields = query.Fields ? query.Fields + ",PrimaryImageAspectRatio" : "PrimaryImageAspectRatio"; + query.ImageTypeLimit = 1; + var hasFilters; + var queryFilters = []; + var filters = instance.getFilters(); + + if (filters.IsPlayed) { + queryFilters.push("IsPlayed"); + hasFilters = true; + } + + if (filters.IsUnplayed) { + queryFilters.push("IsUnplayed"); + hasFilters = true; + } + + if (filters.IsFavorite) { + queryFilters.push("IsFavorite"); + hasFilters = true; + } + + if (filters.IsResumable) { + queryFilters.push("IsResumable"); + hasFilters = true; + } + + if (filters.VideoTypes) { + hasFilters = true; + query.VideoTypes = filters.VideoTypes; + } + + if (filters.GenreIds) { + hasFilters = true; + query.GenreIds = filters.GenreIds; + } + + if (filters.Is4K) { + query.Is4K = true; + hasFilters = true; + } + + if (filters.IsHD) { + query.IsHD = true; + hasFilters = true; + } + + if (filters.IsSD) { + query.IsHD = false; + hasFilters = true; + } + + if (filters.Is3D) { + query.Is3D = true; + hasFilters = true; + } + + if (filters.HasSubtitles) { + query.HasSubtitles = true; + hasFilters = true; + } + + if (filters.HasTrailer) { + query.HasTrailer = true; + hasFilters = true; + } + + if (filters.HasSpecialFeature) { + query.HasSpecialFeature = true; + hasFilters = true; + } + + if (filters.HasThemeSong) { + query.HasThemeSong = true; + hasFilters = true; + } + + if (filters.HasThemeVideo) { + query.HasThemeVideo = true; + hasFilters = true; + } + + query.Filters = queryFilters.length ? queryFilters.join(",") : null; + instance.setFilterStatus(hasFilters); + + if (instance.alphaPicker) { + query.NameStartsWithOrGreater = instance.alphaPicker.value(); + } + + return query; } function updateSortText(instance) { var btnSortText = instance.btnSortText; + if (btnSortText) { - for (var options = instance.getSortMenuOptions(), values = instance.getSortValues(), sortBy = values.sortBy, i = 0, length = options.length; i < length; i++) + var options = instance.getSortMenuOptions(); + var values = instance.getSortValues(); + var sortBy = values.sortBy; + + for (var i = 0, length = options.length; i < length; i++) { if (sortBy === options[i].value) { btnSortText.innerHTML = globalize.translate("SortByValue", options[i].name); - break - } var btnSortIcon = instance.btnSortIcon; - btnSortIcon && (btnSortIcon.innerHTML = "Descending" === values.sortOrder ? "" : "") + break; + } + } + + var btnSortIcon = instance.btnSortIcon; + + if (btnSortIcon) { + btnSortIcon.innerHTML = "Descending" === values.sortOrder ? "" : ""; + } } } function updateItemsContainerForViewType(instance) { - "list" === instance.getViewSettings().imageType ? (instance.itemsContainer.classList.remove("vertical-wrap"), instance.itemsContainer.classList.add("vertical-list")) : (instance.itemsContainer.classList.add("vertical-wrap"), instance.itemsContainer.classList.remove("vertical-list")) + if ("list" === instance.getViewSettings().imageType) { + instance.itemsContainer.classList.remove("vertical-wrap"); + instance.itemsContainer.classList.add("vertical-list"); + } else { + instance.itemsContainer.classList.add("vertical-wrap"); + instance.itemsContainer.classList.remove("vertical-list"); + } } function updateAlphaPickerState(instance, numItems) { if (instance.alphaPicker) { var alphaPicker = instance.alphaPickerElement; + if (alphaPicker) { var values = instance.getSortValues(); - null == numItems && (numItems = 100), "SortName" === values.sortBy && "Ascending" === values.sortOrder && numItems > 40 ? (alphaPicker.classList.remove("hide"), layoutManager.tv ? instance.itemsContainer.parentNode.classList.add("padded-left-withalphapicker") : instance.itemsContainer.parentNode.classList.add("padded-right-withalphapicker")) : (alphaPicker.classList.add("hide"), instance.itemsContainer.parentNode.classList.remove("padded-left-withalphapicker"), instance.itemsContainer.parentNode.classList.remove("padded-right-withalphapicker")) + + if (null == numItems) { + numItems = 100; + } + + if ("SortName" === values.sortBy && "Ascending" === values.sortOrder && numItems > 40) { + alphaPicker.classList.remove("hide"); + + if (layoutManager.tv) { + instance.itemsContainer.parentNode.classList.add("padded-left-withalphapicker"); + } else { + instance.itemsContainer.parentNode.classList.add("padded-right-withalphapicker"); + } + } else { + alphaPicker.classList.add("hide"); + instance.itemsContainer.parentNode.classList.remove("padded-left-withalphapicker"); + instance.itemsContainer.parentNode.classList.remove("padded-right-withalphapicker"); + } } } } function getItems(instance, params, item, sortBy, startIndex, limit) { var apiClient = connectionManager.getApiClient(params.serverId); - if (instance.queryRecursive = !1, "Recordings" === params.type) return apiClient.getLiveTvRecordings(getInitialLiveTvQuery(instance, params)); - if ("Programs" === params.type) return "true" === params.IsAiring ? apiClient.getLiveTvRecommendedPrograms(getInitialLiveTvQuery(instance, params)) : apiClient.getLiveTvPrograms(getInitialLiveTvQuery(instance, params)); - if ("nextup" === params.type) return apiClient.getNextUpEpisodes(modifyQueryWithFilters(instance, { - Limit: limit, - Fields: "PrimaryImageAspectRatio,SeriesInfo,DateCreated,BasicSyncInfo", - UserId: apiClient.getCurrentUserId(), - ImageTypeLimit: 1, - EnableImageTypes: "Primary,Backdrop,Thumb", - EnableTotalRecordCount: !1, - SortBy: sortBy - })); + + instance.queryRecursive = false; + if ("Recordings" === params.type) { + return apiClient.getLiveTvRecordings(getInitialLiveTvQuery(instance, params)); + } + + if ("Programs" === params.type) { + if ("true" === params.IsAiring) { + return apiClient.getLiveTvRecommendedPrograms(getInitialLiveTvQuery(instance, params)); + } + + return apiClient.getLiveTvPrograms(getInitialLiveTvQuery(instance, params)); + } + + if ("nextup" === params.type) { + return apiClient.getNextUpEpisodes(modifyQueryWithFilters(instance, { + Limit: limit, + Fields: "PrimaryImageAspectRatio,SeriesInfo,DateCreated,BasicSyncInfo", + UserId: apiClient.getCurrentUserId(), + ImageTypeLimit: 1, + EnableImageTypes: "Primary,Backdrop,Thumb", + EnableTotalRecordCount: false, + SortBy: sortBy + })); + } + if (!item) { - instance.queryRecursive = !0; + instance.queryRecursive = true; var method = "getItems"; - return "MusicArtist" === params.type ? method = "getArtists" : "Person" === params.type && (method = "getPeople"), apiClient[method](apiClient.getCurrentUserId(), modifyQueryWithFilters(instance, { + + if ("MusicArtist" === params.type) { + method = "getArtists"; + } else if ("Person" === params.type) { + method = "getPeople"; + } + + return apiClient[method](apiClient.getCurrentUserId(), modifyQueryWithFilters(instance, { StartIndex: startIndex, Limit: limit, Fields: "PrimaryImageAspectRatio,SortName", ImageTypeLimit: 1, IncludeItemTypes: "MusicArtist" === params.type || "Person" === params.type ? null : params.type, - Recursive: !0, + Recursive: true, IsFavorite: "true" === params.IsFavorite || null, ArtistIds: params.artistId || null, SortBy: sortBy - })) + })); } + if ("Genre" === item.Type || "MusicGenre" === item.Type || "Studio" === item.Type || "Person" === item.Type) { - instance.queryRecursive = !0; + instance.queryRecursive = true; var query = { StartIndex: startIndex, Limit: limit, Fields: "PrimaryImageAspectRatio,SortName", - Recursive: !0, + Recursive: true, parentId: params.parentId, SortBy: sortBy }; - return "Studio" === item.Type ? query.StudioIds = item.Id : "Genre" === item.Type || "MusicGenre" === item.Type ? query.GenreIds = item.Id : "Person" === item.Type && (query.PersonIds = item.Id), "MusicGenre" === item.Type ? query.IncludeItemTypes = "MusicAlbum" : "GameGenre" === item.Type ? query.IncludeItemTypes = "Game" : "movies" === item.CollectionType ? query.IncludeItemTypes = "Movie" : "tvshows" === item.CollectionType ? query.IncludeItemTypes = "Series" : "Genre" === item.Type ? query.IncludeItemTypes = "Movie,Series,Video" : "Person" === item.Type && (query.IncludeItemTypes = params.type), apiClient.getItems(apiClient.getCurrentUserId(), modifyQueryWithFilters(instance, query)) + + if ("Studio" === item.Type) { + query.StudioIds = item.Id; + } else if ("Genre" === item.Type || "MusicGenre" === item.Type) { + query.GenreIds = item.Id; + } else if ("Person" === item.Type) { + query.PersonIds = item.Id; + } + + if ("MusicGenre" === item.Type) { + query.IncludeItemTypes = "MusicAlbum"; + } else if ("GameGenre" === item.Type) { + query.IncludeItemTypes = "Game"; + } else if ("movies" === item.CollectionType) { + query.IncludeItemTypes = "Movie"; + } else if ("tvshows" === item.CollectionType) { + query.IncludeItemTypes = "Series"; + } else if ("Genre" === item.Type) { + query.IncludeItemTypes = "Movie,Series,Video"; + } else if ("Person" === item.Type) { + query.IncludeItemTypes = params.type; + } + + return apiClient.getItems(apiClient.getCurrentUserId(), modifyQueryWithFilters(instance, query)); } + return apiClient.getItems(apiClient.getCurrentUserId(), modifyQueryWithFilters(instance, { StartIndex: startIndex, Limit: limit, @@ -92,35 +312,44 @@ define(["globalize", "listView", "layoutManager", "userSettings", "focusManager" ImageTypeLimit: 1, ParentId: item.Id, SortBy: sortBy - })) + })); } function getItem(params) { - if ("Recordings" === params.type) return Promise.resolve(null); - if ("Programs" === params.type) return Promise.resolve(null); - if ("nextup" === params.type) return Promise.resolve(null); - var apiClient = connectionManager.getApiClient(params.serverId), - itemId = params.genreId || params.musicGenreId || params.studioId || params.personId || params.parentId; - return itemId ? apiClient.getItem(apiClient.getCurrentUserId(), itemId) : Promise.resolve(null) + if ("Recordings" === params.type || "Programs" === params.type || "nextup" === params.type) { + return Promise.resolve(null); + } + + var apiClient = connectionManager.getApiClient(params.serverId); + var itemId = params.genreId || params.musicGenreId || params.studioId || params.personId || params.parentId; + + if (itemId) { + return apiClient.getItem(apiClient.getCurrentUserId(), itemId); + } + + return Promise.resolve(null); } function showViewSettingsMenu() { var instance = this; - require(["viewSettings"], function(ViewSettings) { - (new ViewSettings).show({ + + require(["viewSettings"], function (ViewSettings) { + new ViewSettings().show({ settingsKey: instance.getSettingsKey(), settings: instance.getViewSettings(), visibleSettings: instance.getVisibleViewSettings() - }).then(function() { - updateItemsContainerForViewType(instance), instance.itemsContainer.refreshItems() - }) - }) + }).then(function () { + updateItemsContainerForViewType(instance); + instance.itemsContainer.refreshItems(); + }); + }); } function showFilterMenu() { var instance = this; - require(["filterMenu"], function(FilterMenu) { - (new FilterMenu).show({ + + require(["filterMenu"], function (FilterMenu) { + new FilterMenu().show({ settingsKey: instance.getSettingsKey(), settings: instance.getFilters(), visibleSettings: instance.getVisibleFilters(), @@ -129,201 +358,497 @@ define(["globalize", "listView", "layoutManager", "userSettings", "focusManager" itemTypes: instance.getItemTypes(), serverId: instance.params.serverId, filterMenuOptions: instance.getFilterMenuOptions() - }).then(function() { - instance.itemsContainer.refreshItems() - }) - }) + }).then(function () { + instance.itemsContainer.refreshItems(); + }); + }); } function showSortMenu() { var instance = this; - require(["sortMenu"], function(SortMenu) { - (new SortMenu).show({ + + require(["sortMenu"], function (SortMenu) { + new SortMenu().show({ settingsKey: instance.getSettingsKey(), settings: instance.getSortValues(), onChange: instance.itemsContainer.refreshItems.bind(instance.itemsContainer), serverId: instance.params.serverId, sortOptions: instance.getSortMenuOptions() - }).then(function() { - updateSortText(instance), updateAlphaPickerState(instance), instance.itemsContainer.refreshItems() - }) - }) + }).then(function () { + updateSortText(instance); + updateAlphaPickerState(instance); + instance.itemsContainer.refreshItems(); + }); + }); } function onNewItemClick() { var instance = this; - require(["playlistEditor"], function(playlistEditor) { - (new playlistEditor).show({ + + require(["playlistEditor"], function (playlistEditor) { + new playlistEditor().show({ items: [], serverId: instance.params.serverId - }) - }) + }); + }); } function hideOrShowAll(elems, hide) { - for (var i = 0, length = elems.length; i < length; i++) hide ? elems[i].classList.add("hide") : elems[i].classList.remove("hide") + for (var i = 0, length = elems.length; i < length; i++) { + if (hide) { + elems[i].classList.add("hide"); + } else { + elems[i].classList.remove("hide"); + } + } } function bindAll(elems, eventName, fn) { - for (var i = 0, length = elems.length; i < length; i++) elems[i].addEventListener(eventName, fn) + for (var i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener(eventName, fn); + } } function ItemsView(view, params) { function fetchData() { - return getItems(self, params, self.currentItem).then(function(result) { - return null == self.totalItemCount && (self.totalItemCount = result.Items ? result.Items.length : result.length), updateAlphaPickerState(self, self.totalItemCount), result - }) + return getItems(self, params, self.currentItem).then(function (result) { + if (null == self.totalItemCount) { + self.totalItemCount = result.Items ? result.Items.length : result.length; + } + + updateAlphaPickerState(self, self.totalItemCount); + return result; + }); } function getItemsHtml(items) { var settings = self.getViewSettings(); - if ("list" === settings.imageType) return listView.getListViewHtml({ - items: items - }); - var shape, preferThumb, preferDisc, preferLogo, defaultShape, item = self.currentItem, - lines = settings.showTitle ? 2 : 0; - "banner" === settings.imageType ? shape = "banner" : "disc" === settings.imageType ? (shape = "square", preferDisc = !0) : "logo" === settings.imageType ? (shape = "backdrop", preferLogo = !0) : "thumb" === settings.imageType ? (shape = "backdrop", preferThumb = !0) : "nextup" === params.type ? (shape = "backdrop", preferThumb = "thumb" === settings.imageType) : "Programs" === params.type || "Recordings" === params.type ? (shape = "true" === params.IsMovie ? "portrait" : "autoVertical", preferThumb = "true" !== params.IsMovie && "auto", defaultShape = "true" === params.IsMovie ? "portrait" : "backdrop") : shape = "autoVertical"; + + if ("list" === settings.imageType) { + return listView.getListViewHtml({ + items: items + }); + } + + var shape; + var preferThumb; + var preferDisc; + var preferLogo; + var defaultShape; + var item = self.currentItem; + var lines = settings.showTitle ? 2 : 0; + + if ("banner" === settings.imageType) { + shape = "banner"; + } else if ("disc" === settings.imageType) { + shape = "square"; + preferDisc = true; + } else if ("logo" === settings.imageType) { + shape = "backdrop"; + preferLogo = true; + } else if ("thumb" === settings.imageType) { + shape = "backdrop"; + preferThumb = true; + } else if ("nextup" === params.type) { + shape = "backdrop"; + preferThumb = "thumb" === settings.imageType; + } else if ("Programs" === params.type || "Recordings" === params.type) { + shape = "true" === params.IsMovie ? "portrait" : "autoVertical"; + preferThumb = "true" !== params.IsMovie ? "auto" : false; + defaultShape = "true" === params.IsMovie ? "portrait" : "backdrop"; + } else { + shape = "autoVertical"; + } + var posterOptions = { shape: shape, showTitle: settings.showTitle, showYear: settings.showTitle, - centerText: !0, - coverImage: !0, + centerText: true, + coverImage: true, preferThumb: preferThumb, preferDisc: preferDisc, preferLogo: preferLogo, - overlayPlayButton: !1, - overlayMoreButton: !0, + overlayPlayButton: false, + overlayMoreButton: true, overlayText: !settings.showTitle, defaultShape: defaultShape, action: "Audio" === params.type ? "playallfromhere" : null }; - if ("nextup" === params.type) posterOptions.showParentTitle = settings.showTitle; - else if ("Person" === params.type) posterOptions.showYear = !1, posterOptions.showParentTitle = !1, lines = 1; - else if ("Audio" === params.type) posterOptions.showParentTitle = settings.showTitle; - else if ("MusicAlbum" === params.type) posterOptions.showParentTitle = settings.showTitle; - else if ("Episode" === params.type) posterOptions.showParentTitle = settings.showTitle; - else if ("MusicArtist" === params.type) posterOptions.showYear = !1, lines = 1; - else if ("Programs" === params.type) { + + if ("nextup" === params.type) { + posterOptions.showParentTitle = settings.showTitle; + } else if ("Person" === params.type) { + posterOptions.showYear = false; + posterOptions.showParentTitle = false; + lines = 1; + } else if ("Audio" === params.type) { + posterOptions.showParentTitle = settings.showTitle; + } else if ("MusicAlbum" === params.type) { + posterOptions.showParentTitle = settings.showTitle; + } else if ("Episode" === params.type) { + posterOptions.showParentTitle = settings.showTitle; + } else if ("MusicArtist" === params.type) { + posterOptions.showYear = false; + lines = 1; + } else if ("Programs" === params.type) { lines = settings.showTitle ? 1 : 0; var showParentTitle = settings.showTitle && "true" !== params.IsMovie; - showParentTitle && lines++; + + if (showParentTitle) { + lines++; + } + var showAirTime = settings.showTitle && "Recordings" !== params.type; - showAirTime && lines++; + + if (showAirTime) { + lines++; + } + var showYear = settings.showTitle && "true" === params.IsMovie && "Recordings" === params.type; - showYear && lines++, posterOptions = Object.assign(posterOptions, { + + if (showYear) { + lines++; + } + + posterOptions = Object.assign(posterOptions, { inheritThumb: "Recordings" === params.type, context: "livetv", showParentTitle: showParentTitle, showAirTime: showAirTime, showAirDateTime: showAirTime, - overlayPlayButton: !1, - overlayMoreButton: !0, + overlayPlayButton: false, + overlayMoreButton: true, showYear: showYear, - coverImage: !0 - }) - } else posterOptions.showParentTitle = settings.showTitle; - return posterOptions.lines = lines, posterOptions.items = items, item && "folders" === item.CollectionType && (posterOptions.context = "folders"), cardBuilder.getCardsHtml(posterOptions) + coverImage: true + }); + } else { + posterOptions.showParentTitle = settings.showTitle; + } + + posterOptions.lines = lines; + posterOptions.items = items; + + if (item && "folders" === item.CollectionType) { + posterOptions.context = "folders"; + } + + return cardBuilder.getCardsHtml(posterOptions); } function initAlphaPicker() { self.scroller = view.querySelector(".scrollFrameY"); var alphaPickerElement = self.alphaPickerElement; - layoutManager.tv ? (alphaPickerElement.classList.add("alphaPicker-fixed-left"), alphaPickerElement.classList.add("focuscontainer-left"), self.itemsContainer.parentNode.classList.add("padded-left-withalphapicker")) : (alphaPickerElement.classList.add("alphaPicker-fixed-right"), alphaPickerElement.classList.add("focuscontainer-right"), self.itemsContainer.parentNode.classList.add("padded-right-withalphapicker")), self.alphaPicker = new alphaPicker({ + + if (layoutManager.tv) { + alphaPickerElement.classList.add("alphaPicker-fixed-left"); + alphaPickerElement.classList.add("focuscontainer-left"); + self.itemsContainer.parentNode.classList.add("padded-left-withalphapicker"); + } else { + alphaPickerElement.classList.add("alphaPicker-fixed-right"); + alphaPickerElement.classList.add("focuscontainer-right"); + self.itemsContainer.parentNode.classList.add("padded-right-withalphapicker"); + } + + self.alphaPicker = new alphaPicker({ element: alphaPickerElement, itemsContainer: layoutManager.tv ? self.itemsContainer : null, itemClass: "card", valueChangeEvent: layoutManager.tv ? null : "click" - }), self.alphaPicker.on("alphavaluechanged", onAlphaPickerValueChanged) + }); + self.alphaPicker.on("alphavaluechanged", onAlphaPickerValueChanged); } function onAlphaPickerValueChanged() { self.alphaPicker.value(); - self.itemsContainer.refreshItems() + self.itemsContainer.refreshItems(); } function setTitle(item) { - Emby.Page.setTitle(getTitle(item) || ""), item && "playlists" === item.CollectionType ? hideOrShowAll(view.querySelectorAll(".btnNewItem"), !1) : hideOrShowAll(view.querySelectorAll(".btnNewItem"), !0) + Emby.Page.setTitle(getTitle(item) || ""); + + if (item && "playlists" === item.CollectionType) { + hideOrShowAll(view.querySelectorAll(".btnNewItem"), false); + } else { + hideOrShowAll(view.querySelectorAll(".btnNewItem"), true); + } } function getTitle(item) { - return "Recordings" === params.type ? globalize.translate("Recordings") : "Programs" === params.type ? "true" === params.IsMovie ? globalize.translate("Movies") : "true" === params.IsSports ? globalize.translate("Sports") : "true" === params.IsKids ? globalize.translate("HeaderForKids") : "true" === params.IsAiring ? globalize.translate("HeaderOnNow") : "true" === params.IsSeries ? globalize.translate("Shows") : "true" === params.IsNews ? globalize.translate("News") : globalize.translate("Programs") : "nextup" === params.type ? globalize.translate("NextUp") : "favoritemovies" === params.type ? globalize.translate("FavoriteMovies") : item ? item.Name : "Movie" === params.type ? globalize.translate("Movies") : "Series" === params.type ? globalize.translate("Shows") : "Season" === params.type ? globalize.translate("Seasons") : "Episode" === params.type ? globalize.translate("Episodes") : "MusicArtist" === params.type ? globalize.translate("Artists") : "MusicAlbum" === params.type ? globalize.translate("Albums") : "Audio" === params.type ? globalize.translate("Songs") : "Video" === params.type ? globalize.translate("Videos") : void 0 + if ("Recordings" === params.type) { + return globalize.translate("Recordings"); + } + + if ("Programs" === params.type) { + if ("true" === params.IsMovie) { + return globalize.translate("Movies"); + } + + if ("true" === params.IsSports) { + return globalize.translate("Sports"); + } + + if ("true" === params.IsKids) { + return globalize.translate("HeaderForKids"); + } + + if ("true" === params.IsAiring) { + return globalize.translate("HeaderOnNow"); + } + + if ("true" === params.IsSeries) { + return globalize.translate("Shows"); + } + + if ("true" === params.IsNews) { + return globalize.translate("News"); + } + + return globalize.translate("Programs"); + } + + if ("nextup" === params.type) { + return globalize.translate("NextUp"); + } + + if ("favoritemovies" === params.type) { + return globalize.translate("FavoriteMovies"); + } + + if (item) { + return item.Name; + } + + if ("Movie" === params.type) { + return globalize.translate("Movies"); + } + + if ("Series" === params.type) { + return globalize.translate("Shows"); + } + + if ("Season" === params.type) { + return globalize.translate("Seasons"); + } + + if ("Episode" === params.type) { + return globalize.translate("Episodes"); + } + + if ("MusicArtist" === params.type) { + return globalize.translate("Artists"); + } + + if ("MusicAlbum" === params.type) { + return globalize.translate("Albums"); + } + + if ("Audio" === params.type) { + return globalize.translate("Songs"); + } + + if ("Video" === params.type) { + return globalize.translate("Videos"); + } + + return void 0; } function play() { var currentItem = self.currentItem; - if (currentItem && !self.hasFilters) return void playbackManager.play({ - items: [currentItem] - }); - getItems(self, self.params, currentItem, null, null, 300).then(function(result) { + + if (currentItem && !self.hasFilters) { playbackManager.play({ - items: result.Items - }) - }) + items: [currentItem] + }); + } else { + getItems(self, self.params, currentItem, null, null, 300).then(function (result) { + playbackManager.play({ + items: result.Items + }); + }); + } } function queue() { var currentItem = self.currentItem; - if (currentItem && !self.hasFilters) return void playbackManager.queue({ - items: [currentItem] - }); - getItems(self, self.params, currentItem, null, null, 300).then(function(result) { + + if (currentItem && !self.hasFilters) { playbackManager.queue({ - items: result.Items - }) - }) + items: [currentItem] + }); + } else { + getItems(self, self.params, currentItem, null, null, 300).then(function (result) { + playbackManager.queue({ + items: result.Items + }); + }); + } } function shuffle() { var currentItem = self.currentItem; - if (currentItem && !self.hasFilters) return void playbackManager.shuffle(currentItem); - getItems(self, self.params, currentItem, "Random", null, 300).then(function(result) { - playbackManager.play({ - items: result.Items - }) - }) + + if (currentItem && !self.hasFilters) { + playbackManager.shuffle(currentItem); + } else { + getItems(self, self.params, currentItem, "Random", null, 300).then(function (result) { + playbackManager.play({ + items: result.Items + }); + }); + } } + var self = this; - self.params = params, this.itemsContainer = view.querySelector(".itemsContainer"), params.parentId ? this.itemsContainer.setAttribute("data-parentid", params.parentId) : "nextup" === params.type ? this.itemsContainer.setAttribute("data-monitor", "videoplayback") : "favoritemovies" === params.type ? this.itemsContainer.setAttribute("data-monitor", "markfavorite") : "Programs" === params.type && this.itemsContainer.setAttribute("data-refreshinterval", "300000"); - var i, length, btnViewSettings = view.querySelectorAll(".btnViewSettings"); - for (i = 0, length = btnViewSettings.length; i < length; i++) btnViewSettings[i].addEventListener("click", showViewSettingsMenu.bind(this)); + self.params = params; + this.itemsContainer = view.querySelector(".itemsContainer"); + + if (params.parentId) { + this.itemsContainer.setAttribute("data-parentid", params.parentId); + } else if ("nextup" === params.type) { + this.itemsContainer.setAttribute("data-monitor", "videoplayback"); + } else if ("favoritemovies" === params.type) { + this.itemsContainer.setAttribute("data-monitor", "markfavorite"); + } else if ("Programs" === params.type) { + this.itemsContainer.setAttribute("data-refreshinterval", "300000"); + } + + var i; + var length; + var btnViewSettings = view.querySelectorAll(".btnViewSettings"); + + for (i = 0, length = btnViewSettings.length; i < length; i++) { + btnViewSettings[i].addEventListener("click", showViewSettingsMenu.bind(this)); + } + var filterButtons = view.querySelectorAll(".btnFilter"); this.filterButtons = filterButtons; var hasVisibleFilters = this.getVisibleFilters().length; + for (i = 0, length = filterButtons.length; i < length; i++) { var btnFilter = filterButtons[i]; - btnFilter.addEventListener("click", showFilterMenu.bind(this)), hasVisibleFilters ? btnFilter.classList.remove("hide") : btnFilter.classList.add("hide") + btnFilter.addEventListener("click", showFilterMenu.bind(this)); + + if (hasVisibleFilters) { + btnFilter.classList.remove("hide"); + } else { + btnFilter.classList.add("hide"); + } } + var sortButtons = view.querySelectorAll(".btnSort"); + for (this.sortButtons = sortButtons, i = 0, length = sortButtons.length; i < length; i++) { var sortButton = sortButtons[i]; - sortButton.addEventListener("click", showSortMenu.bind(this)), "nextup" !== params.type && sortButton.classList.remove("hide") + sortButton.addEventListener("click", showSortMenu.bind(this)); + + if ("nextup" !== params.type) { + sortButton.classList.remove("hide"); + } } - this.btnSortText = view.querySelector(".btnSortText"), this.btnSortIcon = view.querySelector(".btnSortIcon"), bindAll(view.querySelectorAll(".btnNewItem"), "click", onNewItemClick.bind(this)), this.alphaPickerElement = view.querySelector(".alphaPicker"), self.itemsContainer.fetchData = fetchData, self.itemsContainer.getItemsHtml = getItemsHtml, view.addEventListener("viewshow", function(e) { + + this.btnSortText = view.querySelector(".btnSortText"); + this.btnSortIcon = view.querySelector(".btnSortIcon"); + bindAll(view.querySelectorAll(".btnNewItem"), "click", onNewItemClick.bind(this)); + this.alphaPickerElement = view.querySelector(".alphaPicker"); + self.itemsContainer.fetchData = fetchData; + self.itemsContainer.getItemsHtml = getItemsHtml; + view.addEventListener("viewshow", function (e) { var isRestored = e.detail.isRestored; - isRestored || (loading.show(), updateSortText(self), updateItemsContainerForViewType(self)), setTitle(null), getItem(params).then(function(item) { - setTitle(item), self.currentItem = item; + + if (!isRestored) { + loading.show(); + updateSortText(self); + updateItemsContainerForViewType(self); + } + + setTitle(null); + getItem(params).then(function (item) { + setTitle(item); + self.currentItem = item; var refresh = !isRestored; self.itemsContainer.resume({ refresh: refresh - }).then(function() { - loading.hide(), refresh && focusManager.autoFocus(self.itemsContainer) - }), isRestored || item && "PhotoAlbum" !== item.Type && initAlphaPicker(); + }).then(function () { + loading.hide(); + + if (refresh) { + focusManager.autoFocus(self.itemsContainer); + } + }); + + if (!isRestored && item && "PhotoAlbum" !== item.Type) { + initAlphaPicker(); + } + var itemType = item ? item.Type : null; - "MusicGenre" === itemType || "Programs" !== params.type && "Channel" !== itemType ? hideOrShowAll(view.querySelectorAll(".btnPlay"), !1) : hideOrShowAll(view.querySelectorAll(".btnPlay"), !0), "MusicGenre" === itemType || "Programs" !== params.type && "nextup" !== params.type && "Channel" !== itemType ? hideOrShowAll(view.querySelectorAll(".btnShuffle"), !1) : hideOrShowAll(view.querySelectorAll(".btnShuffle"), !0), item && playbackManager.canQueue(item) ? hideOrShowAll(view.querySelectorAll(".btnQueue"), !1) : hideOrShowAll(view.querySelectorAll(".btnQueue"), !0) - }), isRestored || (bindAll(view.querySelectorAll(".btnPlay"), "click", play), bindAll(view.querySelectorAll(".btnQueue"), "click", queue), bindAll(view.querySelectorAll(".btnShuffle"), "click", shuffle)), this.alphaNumericShortcuts = new AlphaNumericShortcuts({ + + if ("MusicGenre" === itemType || "Programs" !== params.type && "Channel" !== itemType) { + hideOrShowAll(view.querySelectorAll(".btnPlay"), false); + } else { + hideOrShowAll(view.querySelectorAll(".btnPlay"), true); + } + + if ("MusicGenre" === itemType || "Programs" !== params.type && "nextup" !== params.type && "Channel" !== itemType) { + hideOrShowAll(view.querySelectorAll(".btnShuffle"), false); + } else { + hideOrShowAll(view.querySelectorAll(".btnShuffle"), true); + } + + if (item && playbackManager.canQueue(item)) { + hideOrShowAll(view.querySelectorAll(".btnQueue"), false); + } else { + hideOrShowAll(view.querySelectorAll(".btnQueue"), true); + } + }); + + if (!isRestored) { + bindAll(view.querySelectorAll(".btnPlay"), "click", play); + bindAll(view.querySelectorAll(".btnQueue"), "click", queue); + bindAll(view.querySelectorAll(".btnShuffle"), "click", shuffle); + } + + this.alphaNumericShortcuts = new AlphaNumericShortcuts({ itemsContainer: self.itemsContainer - }) - }), view.addEventListener("viewhide", function(e) { + }); + }); + view.addEventListener("viewhide", function (e) { var itemsContainer = self.itemsContainer; - itemsContainer && itemsContainer.pause(); + + if (itemsContainer) { + itemsContainer.pause(); + } + var alphaNumericShortcuts = self.alphaNumericShortcuts; - alphaNumericShortcuts && (alphaNumericShortcuts.destroy(), self.alphaNumericShortcuts = null) - }), view.addEventListener("viewdestroy", function() { - self.listController && self.listController.destroy(), self.alphaPicker && (self.alphaPicker.off("alphavaluechanged", onAlphaPickerValueChanged), self.alphaPicker.destroy()), self.currentItem = null, self.scroller = null, self.itemsContainer = null, self.filterButtons = null, self.sortButtons = null, self.btnSortText = null, self.btnSortIcon = null, self.alphaPickerElement = null - }) + + if (alphaNumericShortcuts) { + alphaNumericShortcuts.destroy(); + self.alphaNumericShortcuts = null; + } + }); + view.addEventListener("viewdestroy", function () { + if (self.listController) { + self.listController.destroy(); + } + + if (self.alphaPicker) { + self.alphaPicker.off("alphavaluechanged", onAlphaPickerValueChanged); + self.alphaPicker.destroy(); + } + + self.currentItem = null; + self.scroller = null; + self.itemsContainer = null; + self.filterButtons = null; + self.sortButtons = null; + self.btnSortText = null; + self.btnSortIcon = null; + self.alphaPickerElement = null; + }); } - return ItemsView.prototype.getFilters = function() { + + ItemsView.prototype.getFilters = function () { var basekey = this.getSettingsKey(); return { IsPlayed: "true" === userSettings.getFilter(basekey + "-filter-IsPlayed"), @@ -342,87 +867,211 @@ define(["globalize", "listView", "layoutManager", "userSettings", "focusManager" HasThemeSong: userSettings.getFilter(basekey + "-filter-HasThemeSong"), HasThemeVideo: userSettings.getFilter(basekey + "-filter-HasThemeVideo"), GenreIds: userSettings.getFilter(basekey + "-filter-GenreIds") - } - }, ItemsView.prototype.getSortValues = function() { + }; + }; + + ItemsView.prototype.getSortValues = function () { var basekey = this.getSettingsKey(); return { sortBy: userSettings.getFilter(basekey + "-sortby") || this.getDefaultSortBy(), sortOrder: "Descending" === userSettings.getFilter(basekey + "-sortorder") ? "Descending" : "Ascending" + }; + }; + + ItemsView.prototype.getDefaultSortBy = function () { + var params = this.params; + var sortNameOption = this.getNameSortOption(params); + + if (params.type) { + return sortNameOption.value; } - }, ItemsView.prototype.getDefaultSortBy = function() { - var params = this.params, - sortNameOption = this.getNameSortOption(params); - return params.type ? sortNameOption.value : "IsFolder," + sortNameOption.value - }, ItemsView.prototype.getSortMenuOptions = function() { - var sortBy = [], - params = this.params; - "Programs" === params.type && sortBy.push({ - name: globalize.translate("AirDate"), - value: "StartDate,SortName" - }); + + return "IsFolder," + sortNameOption.value; + }; + + ItemsView.prototype.getSortMenuOptions = function () { + var sortBy = []; + var params = this.params; + + if ("Programs" === params.type) { + sortBy.push({ + name: globalize.translate("AirDate"), + value: "StartDate,SortName" + }); + } + var option = this.getNameSortOption(params); - return option && sortBy.push(option), option = this.getCommunityRatingSortOption(), option && sortBy.push(option), option = this.getCriticRatingSortOption(), option && sortBy.push(option), "Programs" !== params.type && sortBy.push({ - name: globalize.translate("DateAdded"), - value: "DateCreated,SortName" - }), option = this.getDatePlayedSortOption(), option && sortBy.push(option), params.type || (option = this.getNameSortOption(params), sortBy.push({ - name: globalize.translate("Folders"), - value: "IsFolder," + option.value - })), sortBy.push({ + + if (option) { + sortBy.push(option); + } + + option = this.getCommunityRatingSortOption(); + + if (option) { + sortBy.push(option); + } + + option = this.getCriticRatingSortOption(); + + if (option) { + sortBy.push(option); + } + + if ("Programs" !== params.type) { + sortBy.push({ + name: globalize.translate("DateAdded"), + value: "DateCreated,SortName" + }); + } + + option = this.getDatePlayedSortOption(); + + if (option) { + sortBy.push(option); + } + + if (!params.type) { + option = this.getNameSortOption(params); + sortBy.push({ + name: globalize.translate("Folders"), + value: "IsFolder," + option.value + }); + } + + sortBy.push({ name: globalize.translate("ParentalRating"), value: "OfficialRating,SortName" - }), option = this.getPlayCountSortOption(), option && sortBy.push(option), sortBy.push({ + }); + option = this.getPlayCountSortOption(); + + if (option) { + sortBy.push(option); + } + + sortBy.push({ name: globalize.translate("ReleaseDate"), value: "ProductionYear,PremiereDate,SortName" - }), sortBy.push({ + }); + sortBy.push({ name: globalize.translate("Runtime"), value: "Runtime,SortName" - }), sortBy - }, ItemsView.prototype.getNameSortOption = function(params) { - return "Episode" === params.type ? { - name: globalize.translate("Name"), - value: "SeriesName,SortName" - } : { + }); + return sortBy; + }; + + ItemsView.prototype.getNameSortOption = function (params) { + if ("Episode" === params.type) { + return { + name: globalize.translate("Name"), + value: "SeriesName,SortName" + }; + } + + return { name: globalize.translate("Name"), value: "SortName" + }; + }; + + ItemsView.prototype.getPlayCountSortOption = function () { + if ("Programs" === this.params.type) { + return null; } - }, ItemsView.prototype.getPlayCountSortOption = function() { - return "Programs" === this.params.type ? null : { + + return { name: globalize.translate("PlayCount"), value: "PlayCount,SortName" + }; + }; + + ItemsView.prototype.getDatePlayedSortOption = function () { + if ("Programs" === this.params.type) { + return null; } - }, ItemsView.prototype.getDatePlayedSortOption = function() { - return "Programs" === this.params.type ? null : { + + return { name: globalize.translate("DatePlayed"), value: "DatePlayed,SortName" + }; + }; + + ItemsView.prototype.getCriticRatingSortOption = function () { + if ("Programs" === this.params.type) { + return null; } - }, ItemsView.prototype.getCriticRatingSortOption = function() { - return "Programs" === this.params.type ? null : { + + return { name: globalize.translate("CriticRating"), value: "CriticRating,SortName" - } - }, ItemsView.prototype.getCommunityRatingSortOption = function() { + }; + }; + + ItemsView.prototype.getCommunityRatingSortOption = function () { return { name: globalize.translate("CommunityRating"), value: "CommunityRating,SortName" + }; + }; + + ItemsView.prototype.getVisibleFilters = function () { + var filters = []; + var params = this.params; + + if (!("nextup" === params.type)) { + if ("Programs" === params.type) { + filters.push("Genres"); + } else { + params.type; + filters.push("IsUnplayed"); + filters.push("IsPlayed"); + + if (!params.IsFavorite) { + filters.push("IsFavorite"); + } + + filters.push("IsResumable"); + filters.push("VideoType"); + filters.push("HasSubtitles"); + filters.push("HasTrailer"); + filters.push("HasSpecialFeature"); + filters.push("HasThemeSong"); + filters.push("HasThemeVideo"); + } } - }, ItemsView.prototype.getVisibleFilters = function() { - var filters = [], - params = this.params; - return "nextup" === params.type || ("Programs" === params.type ? filters.push("Genres") : (params.type, filters.push("IsUnplayed"), filters.push("IsPlayed"), params.IsFavorite || filters.push("IsFavorite"), filters.push("IsResumable"), filters.push("VideoType"), filters.push("HasSubtitles"), filters.push("HasTrailer"), filters.push("HasSpecialFeature"), filters.push("HasThemeSong"), filters.push("HasThemeVideo"))), filters - }, ItemsView.prototype.setFilterStatus = function(hasFilters) { + + return filters; + }; + + ItemsView.prototype.setFilterStatus = function (hasFilters) { this.hasFilters = hasFilters; var filterButtons = this.filterButtons; - if (filterButtons.length) + + if (filterButtons.length) { for (var i = 0, length = filterButtons.length; i < length; i++) { - var btnFilter = filterButtons[i], - bubble = btnFilter.querySelector(".filterButtonBubble"); + var btnFilter = filterButtons[i]; + var bubble = btnFilter.querySelector(".filterButtonBubble"); + if (!bubble) { - if (!hasFilters) continue; - btnFilter.insertAdjacentHTML("afterbegin", '
            !
            '), btnFilter.classList.add("btnFilterWithBubble"), bubble = btnFilter.querySelector(".filterButtonBubble") + if (!hasFilters) { + continue; + } + + btnFilter.insertAdjacentHTML("afterbegin", '
            !
            '); + btnFilter.classList.add("btnFilterWithBubble"); + bubble = btnFilter.querySelector(".filterButtonBubble"); + } + + if (hasFilters) { + bubble.classList.remove("hide"); + } else { + bubble.classList.add("hide"); } - hasFilters ? bubble.classList.remove("hide") : bubble.classList.add("hide") } - }, ItemsView.prototype.getFilterMenuOptions = function() { + } + }; + + ItemsView.prototype.getFilterMenuOptions = function () { var params = this.params; return { IsAiring: params.IsAiring, @@ -432,31 +1081,126 @@ define(["globalize", "listView", "layoutManager", "userSettings", "focusManager" IsNews: params.IsNews, IsSeries: params.IsSeries, Recursive: this.queryRecursive + }; + }; + + ItemsView.prototype.getVisibleViewSettings = function () { + var item = (this.params, this.currentItem); + var fields = ["showTitle"]; + + if (!item || "PhotoAlbum" !== item.Type && "ChannelFolderItem" !== item.Type) { + fields.push("imageType"); } - }, ItemsView.prototype.getVisibleViewSettings = function() { - var item = (this.params, this.currentItem), - fields = ["showTitle"]; - return (!item || "PhotoAlbum" !== item.Type && "ChannelFolderItem" !== item.Type) && fields.push("imageType"), fields.push("viewType"), fields - }, ItemsView.prototype.getViewSettings = function() { - var basekey = this.getSettingsKey(), - params = this.params, - item = this.currentItem, - showTitle = userSettings.get(basekey + "-showTitle"); - "true" === showTitle ? showTitle = !0 : "false" === showTitle ? showTitle = !1 : "Programs" === params.type || "Recordings" === params.type || "Person" === params.type || "nextup" === params.type || "Audio" === params.type || "MusicAlbum" === params.type || "MusicArtist" === params.type ? showTitle = !0 : item && "PhotoAlbum" !== item.Type && (showTitle = !0); + + fields.push("viewType"); + return fields; + }; + + ItemsView.prototype.getViewSettings = function () { + var basekey = this.getSettingsKey(); + var params = this.params; + var item = this.currentItem; + var showTitle = userSettings.get(basekey + "-showTitle"); + + if ("true" === showTitle) { + showTitle = true; + } else if ("false" === showTitle) { + showTitle = false; + } else if ("Programs" === params.type || "Recordings" === params.type || "Person" === params.type || "nextup" === params.type || "Audio" === params.type || "MusicAlbum" === params.type || "MusicArtist" === params.type) { + showTitle = true; + } else if (item && "PhotoAlbum" !== item.Type) { + showTitle = true; + } + var imageType = userSettings.get(basekey + "-imageType"); - return imageType || "nextup" === params.type && (imageType = "thumb"), { + + if (!imageType && "nextup" === params.type) { + imageType = "thumb"; + } + + return { showTitle: showTitle, showYear: "false" !== userSettings.get(basekey + "-showYear"), imageType: imageType || "primary", viewType: userSettings.get(basekey + "-viewType") || "images" - } - }, ItemsView.prototype.getItemTypes = function() { + }; + }; + + ItemsView.prototype.getItemTypes = function () { var params = this.params; - return "nextup" === params.type ? ["Episode"] : "Programs" === params.type ? ["Program"] : [] - }, ItemsView.prototype.getSettingsKey = function() { + + if ("nextup" === params.type) { + return ["Episode"]; + } + + if ("Programs" === params.type) { + return ["Program"]; + } + + return []; + }; + + ItemsView.prototype.getSettingsKey = function () { var values = []; values.push("items"); var params = this.params; - return params.type ? values.push(params.type) : params.parentId && values.push(params.parentId), params.IsAiring && values.push("IsAiring"), params.IsMovie && values.push("IsMovie"), params.IsKids && values.push("IsKids"), params.IsSports && values.push("IsSports"), params.IsNews && values.push("IsNews"), params.IsSeries && values.push("IsSeries"), params.IsFavorite && values.push("IsFavorite"), params.genreId && values.push("Genre"), params.musicGenreId && values.push("MusicGenre"), params.studioId && values.push("Studio"), params.personId && values.push("Person"), params.parentId && values.push("Folder"), values.join("-") - }, ItemsView + + if (params.type) { + values.push(params.type); + } else if (params.parentId) { + values.push(params.parentId); + } + + if (params.IsAiring) { + values.push("IsAiring"); + } + + if (params.IsMovie) { + values.push("IsMovie"); + } + + if (params.IsKids) { + values.push("IsKids"); + } + + if (params.IsSports) { + values.push("IsSports"); + } + + if (params.IsNews) { + values.push("IsNews"); + } + + if (params.IsSeries) { + values.push("IsSeries"); + } + + if (params.IsFavorite) { + values.push("IsFavorite"); + } + + if (params.genreId) { + values.push("Genre"); + } + + if (params.musicGenreId) { + values.push("MusicGenre"); + } + + if (params.studioId) { + values.push("Studio"); + } + + if (params.personId) { + values.push("Person"); + } + + if (params.parentId) { + values.push("Folder"); + } + + return values.join("-"); + }; + + return ItemsView; }); diff --git a/src/controllers/livetv/livetvchannels.js b/src/controllers/livetv/livetvchannels.js index cc2eda5053..3e310a17a3 100644 --- a/src/controllers/livetv/livetvchannels.js +++ b/src/controllers/livetv/livetvchannels.js @@ -1,89 +1,119 @@ -define(["cardBuilder", "imageLoader", "libraryBrowser", "loading", "events", "emby-itemscontainer"], function(cardBuilder, imageLoader, libraryBrowser, loading, events) { +define(["cardBuilder", "imageLoader", "libraryBrowser", "loading", "events", "emby-itemscontainer"], function (cardBuilder, imageLoader, libraryBrowser, loading, events) { "use strict"; - return function(view, params, tabContent) { + + return function (view, params, tabContent) { function getPageData() { - return pageData || (pageData = { - query: { - StartIndex: 0, - Limit: 100, - Fields: "PrimaryImageAspectRatio" - } - }), pageData + if (!pageData) { + pageData = { + query: { + StartIndex: 0, + Limit: 100, + Fields: "PrimaryImageAspectRatio" + } + }; + } + + return pageData; } function getQuery() { - return getPageData().query + return getPageData().query; } function getChannelsHtml(channels) { return cardBuilder.getCardsHtml({ items: channels, shape: "square", - showTitle: !0, - lazy: !0, - cardLayout: !0, - showDetailsMenu: !0, - showCurrentProgram: !0, - showCurrentProgramTime: !0 - }) + showTitle: true, + lazy: true, + cardLayout: true, + showDetailsMenu: true, + showCurrentProgram: true, + showCurrentProgramTime: true + }); } function renderChannels(context, result) { function onNextPageClick() { - if (isLoading) return; - query.StartIndex += query.Limit, reloadItems(context) + if (isLoading) { + return; + } + + query.StartIndex += query.Limit; + reloadItems(context); } function onPreviousPageClick() { - if (isLoading) return; - query.StartIndex -= query.Limit, reloadItems(context) + if (isLoading) { + return; + } + + query.StartIndex -= query.Limit; + reloadItems(context); } + var query = getQuery(); context.querySelector(".paging").innerHTML = libraryBrowser.getQueryPagingHtml({ startIndex: query.StartIndex, limit: query.Limit, totalRecordCount: result.TotalRecordCount, - showLimit: !1, - updatePageSizeSetting: !1, - filterButton: !1 + showLimit: false, + updatePageSizeSetting: false, + filterButton: false }); - var html = getChannelsHtml(result.Items), - elem = context.querySelector("#items"); - elem.innerHTML = html, imageLoader.lazyChildren(elem); - var i, length, elems; - for (elems = context.querySelectorAll(".btnNextPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onNextPageClick); - for (elems = context.querySelectorAll(".btnPreviousPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onPreviousPageClick) + var html = getChannelsHtml(result.Items); + var elem = context.querySelector("#items"); + elem.innerHTML = html; + imageLoader.lazyChildren(elem); + var i; + var length; + var elems; + + for (elems = context.querySelectorAll(".btnNextPage"), i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener("click", onNextPageClick); + } + + for (elems = context.querySelectorAll(".btnPreviousPage"), i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener("click", onPreviousPageClick); + } } function showFilterMenu(context) { - require(["components/filterdialog/filterdialog"], function(filterDialogFactory) { + require(["components/filterdialog/filterdialog"], function (filterDialogFactory) { var filterDialog = new filterDialogFactory({ query: getQuery(), mode: "livetvchannels", serverId: ApiClient.serverId() }); - events.on(filterDialog, "filterchange", function() { - reloadItems(context) - }), filterDialog.show() - }) + events.on(filterDialog, "filterchange", function () { + reloadItems(context); + }); + filterDialog.show(); + }); } function reloadItems(context, save) { loading.show(); isLoading = true; - var query = getQuery(), - apiClient = ApiClient; - query.UserId = apiClient.getCurrentUserId(), apiClient.getLiveTvChannels(query).then(function(result) { + var query = getQuery(); + var apiClient = ApiClient; + query.UserId = apiClient.getCurrentUserId(); + apiClient.getLiveTvChannels(query).then(function (result) { renderChannels(context, result); loading.hide(); isLoading = false; - }) + }); } - var pageData, self = this, isLoading = false; - tabContent.querySelector(".btnFilter").addEventListener("click", function() { - showFilterMenu(tabContent) - }), self.renderTab = function() { - reloadItems(tabContent) - } - } + + var pageData; + var self = this; + var isLoading = false; + tabContent.querySelector(".btnFilter").addEventListener("click", function () { + showFilterMenu(tabContent); + }); + + self.renderTab = function () { + reloadItems(tabContent); + }; + }; }); diff --git a/src/controllers/livetv/livetvguide.js b/src/controllers/livetv/livetvguide.js index 3c8b3f4109..f7c2f1baaa 100644 --- a/src/controllers/livetv/livetvguide.js +++ b/src/controllers/livetv/livetvguide.js @@ -1,16 +1,29 @@ -define(["tvguide"], function(tvguide) { +define(["tvguide"], function (tvguide) { "use strict"; - return function(view, params, tabContent) { - var guideInstance, self = this; - self.renderTab = function() { - guideInstance || (guideInstance = new tvguide({ - element: tabContent, - serverId: ApiClient.serverId() - })) - }, self.onShow = function() { - guideInstance && guideInstance.resume() - }, self.onHide = function() { - guideInstance && guideInstance.pause() - } - } -}); \ No newline at end of file + + return function (view, params, tabContent) { + var guideInstance; + var self = this; + + self.renderTab = function () { + if (!guideInstance) { + guideInstance = new tvguide({ + element: tabContent, + serverId: ApiClient.serverId() + }); + } + }; + + self.onShow = function () { + if (guideInstance) { + guideInstance.resume(); + } + }; + + self.onHide = function () { + if (guideInstance) { + guideInstance.pause(); + } + }; + }; +}); diff --git a/src/controllers/livetv/livetvrecordings.js b/src/controllers/livetv/livetvrecordings.js index f82b150a21..ed3ae24087 100644 --- a/src/controllers/livetv/livetvrecordings.js +++ b/src/controllers/livetv/livetvrecordings.js @@ -1,69 +1,106 @@ -define(["layoutManager", "loading", "cardBuilder", "apphost", "imageLoader", "scripts/livetvcomponents", "listViewStyle", "emby-itemscontainer"], function(layoutManager, loading, cardBuilder, appHost, imageLoader) { +define(["layoutManager", "loading", "cardBuilder", "apphost", "imageLoader", "scripts/livetvcomponents", "listViewStyle", "emby-itemscontainer"], function (layoutManager, loading, cardBuilder, appHost, imageLoader) { "use strict"; function renderRecordings(elem, recordings, cardOptions, scrollX) { - recordings.length ? elem.classList.remove("hide") : elem.classList.add("hide"); + if (recordings.length) { + elem.classList.remove("hide"); + } else { + elem.classList.add("hide"); + } + var recordingItems = elem.querySelector(".recordingItems"); - scrollX ? (recordingItems.classList.add("scrollX"), recordingItems.classList.add("hiddenScrollX"), recordingItems.classList.remove("vertical-wrap")) : (recordingItems.classList.remove("scrollX"), recordingItems.classList.remove("hiddenScrollX"), recordingItems.classList.add("vertical-wrap")); + + if (scrollX) { + recordingItems.classList.add("scrollX"); + recordingItems.classList.add("hiddenScrollX"); + recordingItems.classList.remove("vertical-wrap"); + } else { + recordingItems.classList.remove("scrollX"); + recordingItems.classList.remove("hiddenScrollX"); + recordingItems.classList.add("vertical-wrap"); + } + appHost.supports("imageanalysis"); recordingItems.innerHTML = cardBuilder.getCardsHtml(Object.assign({ items: recordings, shape: scrollX ? "autooverflow" : "auto", defaultShape: scrollX ? "overflowBackdrop" : "backdrop", - showTitle: !0, - showParentTitle: !0, - coverImage: !0, - cardLayout: !1, - centerText: !0, + showTitle: true, + showParentTitle: true, + coverImage: true, + cardLayout: false, + centerText: true, allowBottomPadding: !scrollX, preferThumb: "auto", - overlayText: !1 - }, cardOptions || {})), imageLoader.lazyChildren(recordingItems) + overlayText: false + }, cardOptions || {})); + imageLoader.lazyChildren(recordingItems); } function renderLatestRecordings(context, promise) { - promise.then(function(result) { + promise.then(function (result) { renderRecordings(context.querySelector("#latestRecordings"), result.Items, { - showYear: !0, + showYear: true, lines: 2 - }, !1), loading.hide() - }) + }, false); + loading.hide(); + }); } function renderRecordingFolders(context, promise) { - promise.then(function(result) { + promise.then(function (result) { renderRecordings(context.querySelector("#recordingFolders"), result.Items, { - showYear: !1, - showParentTitle: !1 - }, !1) - }) + showYear: false, + showParentTitle: false + }, false); + }); } function onMoreClick(e) { - var type = this.getAttribute("data-type"), - serverId = ApiClient.serverId(); + var type = this.getAttribute("data-type"); + var serverId = ApiClient.serverId(); + switch (type) { case "latest": - Dashboard.navigate("list.html?type=Recordings&serverId=" + serverId) + Dashboard.navigate("list.html?type=Recordings&serverId=" + serverId); } } - return function(view, params, tabContent) { + + return function (view, params, tabContent) { function enableFullRender() { - return (new Date).getTime() - lastFullRender > 3e5 + return new Date().getTime() - lastFullRender > 300000; } - var foldersPromise, latestPromise, self = this, - lastFullRender = 0; - for (var moreButtons = tabContent.querySelectorAll(".more"), i = 0, length = moreButtons.length; i < length; i++) moreButtons[i].addEventListener("click", onMoreClick); - self.preRender = function() { - enableFullRender() && (latestPromise = ApiClient.getLiveTvRecordings({ - UserId: Dashboard.getCurrentUserId(), - Limit: 12, - Fields: "CanDelete,PrimaryImageAspectRatio,BasicSyncInfo", - EnableTotalRecordCount: !1, - EnableImageTypes: "Primary,Thumb,Backdrop" - }), foldersPromise = ApiClient.getRecordingFolders(Dashboard.getCurrentUserId())) - }, self.renderTab = function() { - enableFullRender() && (loading.show(), renderLatestRecordings(tabContent, latestPromise), renderRecordingFolders(tabContent, foldersPromise), lastFullRender = (new Date).getTime()) + + var foldersPromise; + var latestPromise; + var self = this; + var lastFullRender = 0; + var moreButtons = tabContent.querySelectorAll(".more"); + + for (var i = 0, length = moreButtons.length; i < length; i++) { + moreButtons[i].addEventListener("click", onMoreClick); } - } -}); \ No newline at end of file + + self.preRender = function () { + if (enableFullRender()) { + latestPromise = ApiClient.getLiveTvRecordings({ + UserId: Dashboard.getCurrentUserId(), + Limit: 12, + Fields: "CanDelete,PrimaryImageAspectRatio,BasicSyncInfo", + EnableTotalRecordCount: false, + EnableImageTypes: "Primary,Thumb,Backdrop" + }); + foldersPromise = ApiClient.getRecordingFolders(Dashboard.getCurrentUserId()); + } + }; + + self.renderTab = function () { + if (enableFullRender()) { + loading.show(); + renderLatestRecordings(tabContent, latestPromise); + renderRecordingFolders(tabContent, foldersPromise); + lastFullRender = new Date().getTime(); + } + }; + }; +}); diff --git a/src/controllers/livetv/livetvschedule.js b/src/controllers/livetv/livetvschedule.js index 24ece42dbe..3ee56a2a95 100644 --- a/src/controllers/livetv/livetvschedule.js +++ b/src/controllers/livetv/livetvschedule.js @@ -1,27 +1,50 @@ -define(["layoutManager", "cardBuilder", "apphost", "imageLoader", "loading", "scripts/livetvcomponents", "emby-button", "emby-itemscontainer"], function(layoutManager, cardBuilder, appHost, imageLoader, loading) { +define(["layoutManager", "cardBuilder", "apphost", "imageLoader", "loading", "scripts/livetvcomponents", "emby-button", "emby-itemscontainer"], function (layoutManager, cardBuilder, appHost, imageLoader, loading) { "use strict"; function enableScrollX() { - return !layoutManager.desktop + return !layoutManager.desktop; } function renderRecordings(elem, recordings, cardOptions) { - recordings.length ? elem.classList.remove("hide") : elem.classList.add("hide"); + if (recordings.length) { + elem.classList.remove("hide"); + } else { + elem.classList.add("hide"); + } + var recordingItems = elem.querySelector(".recordingItems"); - enableScrollX() ? (recordingItems.classList.add("scrollX"), layoutManager.tv && recordingItems.classList.add("smoothScrollX"), recordingItems.classList.add("hiddenScrollX"), recordingItems.classList.remove("vertical-wrap")) : (recordingItems.classList.remove("scrollX"), recordingItems.classList.remove("smoothScrollX"), recordingItems.classList.remove("hiddenScrollX"), recordingItems.classList.add("vertical-wrap")); - var supportsImageAnalysis = appHost.supports("imageanalysis"), - cardLayout = appHost.preferVisualCards || supportsImageAnalysis; - cardLayout = !1, recordingItems.innerHTML = cardBuilder.getCardsHtml(Object.assign({ + + if (enableScrollX()) { + recordingItems.classList.add("scrollX"); + + if (layoutManager.tv) { + recordingItems.classList.add("smoothScrollX"); + } + + recordingItems.classList.add("hiddenScrollX"); + recordingItems.classList.remove("vertical-wrap"); + } else { + recordingItems.classList.remove("scrollX"); + recordingItems.classList.remove("smoothScrollX"); + recordingItems.classList.remove("hiddenScrollX"); + recordingItems.classList.add("vertical-wrap"); + } + + var supportsImageAnalysis = appHost.supports("imageanalysis"); + var cardLayout = appHost.preferVisualCards || supportsImageAnalysis; + cardLayout = false; + recordingItems.innerHTML = cardBuilder.getCardsHtml(Object.assign({ items: recordings, shape: enableScrollX() ? "autooverflow" : "auto", - showTitle: !0, - showParentTitle: !0, - coverImage: !0, + showTitle: true, + showParentTitle: true, + coverImage: true, cardLayout: cardLayout, centerText: !cardLayout, allowBottomPadding: !enableScrollX(), preferThumb: "auto" - }, cardOptions || {})), imageLoader.lazyChildren(recordingItems) + }, cardOptions || {})); + imageLoader.lazyChildren(recordingItems); } function getBackdropShape() { @@ -29,52 +52,72 @@ define(["layoutManager", "cardBuilder", "apphost", "imageLoader", "loading", "sc } function renderActiveRecordings(context, promise) { - promise.then(function(result) { + promise.then(function (result) { renderRecordings(context.querySelector("#activeRecordings"), result.Items, { shape: enableScrollX() ? "autooverflow" : "auto", defaultShape: getBackdropShape(), - showParentTitle: !1, - showParentTitleOrTitle: !0, - showTitle: !1, - showAirTime: !0, - showAirEndTime: !0, - showChannelName: !0, - coverImage: !0, - overlayText: !1, - overlayMoreButton: !0 - }) - }) + showParentTitle: false, + showParentTitleOrTitle: true, + showTitle: false, + showAirTime: true, + showAirEndTime: true, + showChannelName: true, + coverImage: true, + overlayText: false, + overlayMoreButton: true + }); + }); } function renderTimers(context, timers, options) { - LiveTvHelpers.getTimersHtml(timers, options).then(function(html) { + LiveTvHelpers.getTimersHtml(timers, options).then(function (html) { var elem = context; - html ? elem.classList.remove("hide") : elem.classList.add("hide"), elem.querySelector(".recordingItems").innerHTML = html, imageLoader.lazyChildren(elem) - }) + + if (html) { + elem.classList.remove("hide"); + } else { + elem.classList.add("hide"); + } + + elem.querySelector(".recordingItems").innerHTML = html; + imageLoader.lazyChildren(elem); + }); } function renderUpcomingRecordings(context, promise) { - promise.then(function(result) { - renderTimers(context.querySelector("#upcomingRecordings"), result.Items), loading.hide() - }) + promise.then(function (result) { + renderTimers(context.querySelector("#upcomingRecordings"), result.Items); + loading.hide(); + }); } - return function(view, params, tabContent) { - var activeRecordingsPromise, upcomingRecordingsPromise, self = this; - tabContent.querySelector("#upcomingRecordings .recordingItems").addEventListener("timercancelled", function() { - self.preRender(), self.renderTab() - }), self.preRender = function() { + + return function (view, params, tabContent) { + var activeRecordingsPromise; + var upcomingRecordingsPromise; + var self = this; + tabContent.querySelector("#upcomingRecordings .recordingItems").addEventListener("timercancelled", function () { + self.preRender(); + self.renderTab(); + }); + + self.preRender = function () { activeRecordingsPromise = ApiClient.getLiveTvRecordings({ UserId: Dashboard.getCurrentUserId(), - IsInProgress: !0, + IsInProgress: true, Fields: "CanDelete,PrimaryImageAspectRatio,BasicSyncInfo", - EnableTotalRecordCount: !1, + EnableTotalRecordCount: false, EnableImageTypes: "Primary,Thumb,Backdrop" - }), upcomingRecordingsPromise = ApiClient.getLiveTvTimers({ - IsActive: !1, - IsScheduled: !0 - }) - }, self.renderTab = function() { - loading.show(), renderActiveRecordings(tabContent, activeRecordingsPromise), renderUpcomingRecordings(tabContent, upcomingRecordingsPromise) - } - } -}); \ No newline at end of file + }); + upcomingRecordingsPromise = ApiClient.getLiveTvTimers({ + IsActive: false, + IsScheduled: true + }); + }; + + self.renderTab = function () { + loading.show(); + renderActiveRecordings(tabContent, activeRecordingsPromise); + renderUpcomingRecordings(tabContent, upcomingRecordingsPromise); + }; + }; +}); diff --git a/src/controllers/livetv/livetvseriestimers.js b/src/controllers/livetv/livetvseriestimers.js index 5acd9f326c..9c95cfa91f 100644 --- a/src/controllers/livetv/livetvseriestimers.js +++ b/src/controllers/livetv/livetvseriestimers.js @@ -1,4 +1,4 @@ -define(["datetime", "cardBuilder", "imageLoader", "apphost", "loading", "paper-icon-button-light", "emby-button"], function(datetime, cardBuilder, imageLoader, appHost, loading) { +define(["datetime", "cardBuilder", "imageLoader", "apphost", "loading", "paper-icon-button-light", "emby-button"], function (datetime, cardBuilder, imageLoader, appHost, loading) { "use strict"; function renderTimers(context, timers) { @@ -8,36 +8,44 @@ define(["datetime", "cardBuilder", "imageLoader", "apphost", "loading", "paper-i items: timers, shape: "auto", defaultShape: "portrait", - showTitle: !0, - cardLayout: !1, + showTitle: true, + cardLayout: false, preferThumb: "auto", - coverImage: !0, - overlayText: !1, - showSeriesTimerTime: !0, - showSeriesTimerChannel: !0, - centerText: !0, - overlayMoreButton: !0, + coverImage: true, + overlayText: false, + showSeriesTimerTime: true, + showSeriesTimerChannel: true, + centerText: true, + overlayMoreButton: true, lines: 3 }); var elem = context.querySelector("#items"); - elem.innerHTML = html, imageLoader.lazyChildren(elem), loading.hide() + elem.innerHTML = html; + imageLoader.lazyChildren(elem); + loading.hide(); } function reload(context, promise) { - loading.show(), promise.then(function(result) { - renderTimers(context, result.Items) - }) + loading.show(); + promise.then(function (result) { + renderTimers(context, result.Items); + }); } + var query = { SortBy: "SortName", SortOrder: "Ascending" }; - return function(view, params, tabContent) { - var timersPromise, self = this; - self.preRender = function() { - timersPromise = ApiClient.getLiveTvSeriesTimers(query) - }, self.renderTab = function() { - reload(tabContent, timersPromise) - } - } -}); \ No newline at end of file + return function (view, params, tabContent) { + var timersPromise; + var self = this; + + self.preRender = function () { + timersPromise = ApiClient.getLiveTvSeriesTimers(query); + }; + + self.renderTab = function () { + reload(tabContent, timersPromise); + }; + }; +}); diff --git a/src/controllers/livetv/livetvsuggested.js b/src/controllers/livetv/livetvsuggested.js index 4fc51467e6..509b7f521c 100644 --- a/src/controllers/livetv/livetvsuggested.js +++ b/src/controllers/livetv/livetvsuggested.js @@ -23,6 +23,7 @@ define(["layoutManager", "userSettings", "inputManager", "loading", "globalize", if (enableScrollX()) { return 12; } + return 9; } @@ -150,15 +151,22 @@ define(["layoutManager", "userSettings", "inputManager", "loading", "globalize", } function getTabs() { - return [ - { name: globalize.translate("Programs") }, - { name: globalize.translate("TabGuide") }, - { name: globalize.translate("TabChannels") }, - { name: globalize.translate("TabRecordings") }, - { name: globalize.translate("HeaderSchedule") }, - { name: globalize.translate("TabSeries") }, - { name: globalize.translate("ButtonSearch"), cssClass: "searchTabButton" } - ]; + return [{ + name: globalize.translate("Programs") + }, { + name: globalize.translate("TabGuide") + }, { + name: globalize.translate("TabChannels") + }, { + name: globalize.translate("TabRecordings") + }, { + name: globalize.translate("HeaderSchedule") + }, { + name: globalize.translate("TabSeries") + }, { + name: globalize.translate("ButtonSearch"), + cssClass: "searchTabButton" + }]; } function setScrollClasses(elem, scrollX) { @@ -183,6 +191,7 @@ define(["layoutManager", "userSettings", "inputManager", "loading", "globalize", if (userSettings.get("landing-" + folderId) === "guide") { return 1; } + return 0; } @@ -220,21 +229,27 @@ define(["layoutManager", "userSettings", "inputManager", "loading", "globalize", switch (index) { case 0: break; + case 1: depends.push("controllers/livetv/livetvguide"); break; + case 2: depends.push("controllers/livetv/livetvchannels"); break; + case 3: depends.push("controllers/livetv/livetvrecordings"); break; + case 4: depends.push("controllers/livetv/livetvschedule"); break; + case 5: depends.push("controllers/livetv/livetvseriestimers"); break; + case 6: depends.push("scripts/searchtab"); } @@ -251,6 +266,7 @@ define(["layoutManager", "userSettings", "inputManager", "loading", "globalize", if (!controller) { tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"); + if (0 === index) { controller = self; } else if (6 === index) { @@ -260,6 +276,7 @@ define(["layoutManager", "userSettings", "inputManager", "loading", "globalize", } else { controller = new controllerFactory(view, params, tabContent); } + tabControllers[index] = controller; if (controller.initTab) { @@ -347,15 +364,18 @@ define(["layoutManager", "userSettings", "inputManager", "loading", "globalize", }); view.addEventListener("viewshow", function (evt) { isViewRestored = evt.detail.isRestored; + if (!isViewRestored) { mainTabsManager.selectedTabIndex(initialTabIndex); } + inputManager.on(window, onInputCommand); }); - view.addEventListener("viewbeforehide", function (e__u) { + view.addEventListener("viewbeforehide", function (e) { if (currentTabController && currentTabController.onHide) { currentTabController.onHide(); } + inputManager.off(window, onInputCommand); }); view.addEventListener("viewdestroy", function (evt) { diff --git a/src/controllers/livetvguideprovider.js b/src/controllers/livetvguideprovider.js index 40617cdb90..a58917f22d 100644 --- a/src/controllers/livetvguideprovider.js +++ b/src/controllers/livetvguideprovider.js @@ -1,26 +1,30 @@ -define(["events", "loading"], function(events, loading) { +define(["events", "loading"], function (events, loading) { "use strict"; function onListingsSubmitted() { - Dashboard.navigate("livetvstatus.html") + Dashboard.navigate("livetvstatus.html"); } function init(page, type, providerId) { var url = "components/tvproviders/" + type + ".js"; - require([url], function(factory) { + + require([url], function (factory) { var instance = new factory(page, providerId, {}); - events.on(instance, "submitted", onListingsSubmitted), instance.init() - }) + events.on(instance, "submitted", onListingsSubmitted); + instance.init(); + }); } function loadTemplate(page, type, providerId) { - require(["text!./components/tvproviders/" + type + ".template.html"], function(html) { - page.querySelector(".providerTemplate").innerHTML = Globalize.translateDocument(html), init(page, type, providerId) - }) + require(["text!./components/tvproviders/" + type + ".template.html"], function (html) { + page.querySelector(".providerTemplate").innerHTML = Globalize.translateDocument(html); + init(page, type, providerId); + }); } - pageIdOn("pageshow", "liveTvGuideProviderPage", function() { + + pageIdOn("pageshow", "liveTvGuideProviderPage", function () { loading.show(); var providerId = getParameterByName("id"); - loadTemplate(this, getParameterByName("type"), providerId) - }) -}); \ No newline at end of file + loadTemplate(this, getParameterByName("type"), providerId); + }); +}); diff --git a/src/controllers/livetvsettings.js b/src/controllers/livetvsettings.js index 422257e33d..2b11071c75 100644 --- a/src/controllers/livetvsettings.js +++ b/src/controllers/livetvsettings.js @@ -1,79 +1,127 @@ -define(["jQuery", "loading", "fnchecked", "emby-button"], function($, loading) { +define(["jQuery", "loading", "fnchecked", "emby-button"], function ($, loading) { "use strict"; function loadPage(page, config) { - $(".liveTvSettingsForm", page).show(), $(".noLiveTvServices", page).hide(), $("#selectGuideDays", page).val(config.GuideDays || ""), $("#txtPrePaddingMinutes", page).val(config.PrePaddingSeconds / 60), $("#txtPostPaddingMinutes", page).val(config.PostPaddingSeconds / 60), page.querySelector("#txtRecordingPath").value = config.RecordingPath || "", page.querySelector("#txtMovieRecordingPath").value = config.MovieRecordingPath || "", page.querySelector("#txtSeriesRecordingPath").value = config.SeriesRecordingPath || "", page.querySelector("#txtPostProcessor").value = config.RecordingPostProcessor || "", page.querySelector("#txtPostProcessorArguments").value = config.RecordingPostProcessorArguments || "", loading.hide() + $(".liveTvSettingsForm", page).show(); + $(".noLiveTvServices", page).hide(); + $("#selectGuideDays", page).val(config.GuideDays || ""); + $("#txtPrePaddingMinutes", page).val(config.PrePaddingSeconds / 60); + $("#txtPostPaddingMinutes", page).val(config.PostPaddingSeconds / 60); + page.querySelector("#txtRecordingPath").value = config.RecordingPath || ""; + page.querySelector("#txtMovieRecordingPath").value = config.MovieRecordingPath || ""; + page.querySelector("#txtSeriesRecordingPath").value = config.SeriesRecordingPath || ""; + page.querySelector("#txtPostProcessor").value = config.RecordingPostProcessor || ""; + page.querySelector("#txtPostProcessorArguments").value = config.RecordingPostProcessorArguments || ""; + loading.hide(); } function onSubmit() { loading.show(); var form = this; - return ApiClient.getNamedConfiguration("livetv").then(function(config) { + ApiClient.getNamedConfiguration("livetv").then(function (config) { config.GuideDays = $("#selectGuideDays", form).val() || null; - var recordingPath = form.querySelector("#txtRecordingPath").value || null, - movieRecordingPath = form.querySelector("#txtMovieRecordingPath").value || null, - seriesRecordingPath = form.querySelector("#txtSeriesRecordingPath").value || null, - recordingPathChanged = recordingPath != config.RecordingPath || movieRecordingPath != config.MovieRecordingPath || seriesRecordingPath != config.SeriesRecordingPath; - config.RecordingPath = recordingPath, config.MovieRecordingPath = movieRecordingPath, config.SeriesRecordingPath = seriesRecordingPath, config.RecordingEncodingFormat = "mkv", config.PrePaddingSeconds = 60 * $("#txtPrePaddingMinutes", form).val(), config.PostPaddingSeconds = 60 * $("#txtPostPaddingMinutes", form).val(), config.RecordingPostProcessor = $("#txtPostProcessor", form).val(), config.RecordingPostProcessorArguments = $("#txtPostProcessorArguments", form).val(), ApiClient.updateNamedConfiguration("livetv", config).then(function() { - Dashboard.processServerConfigurationUpdateResult(), showSaveMessage(recordingPathChanged) - }) - }), !1 + var recordingPath = form.querySelector("#txtRecordingPath").value || null; + var movieRecordingPath = form.querySelector("#txtMovieRecordingPath").value || null; + var seriesRecordingPath = form.querySelector("#txtSeriesRecordingPath").value || null; + var recordingPathChanged = recordingPath != config.RecordingPath || movieRecordingPath != config.MovieRecordingPath || seriesRecordingPath != config.SeriesRecordingPath; + config.RecordingPath = recordingPath; + config.MovieRecordingPath = movieRecordingPath; + config.SeriesRecordingPath = seriesRecordingPath; + config.RecordingEncodingFormat = "mkv"; + config.PrePaddingSeconds = 60 * $("#txtPrePaddingMinutes", form).val(); + config.PostPaddingSeconds = 60 * $("#txtPostPaddingMinutes", form).val(); + config.RecordingPostProcessor = $("#txtPostProcessor", form).val(); + config.RecordingPostProcessorArguments = $("#txtPostProcessorArguments", form).val(); + ApiClient.updateNamedConfiguration("livetv", config).then(function () { + Dashboard.processServerConfigurationUpdateResult(); + showSaveMessage(recordingPathChanged); + }); + }); + return false; } function showSaveMessage(recordingPathChanged) { var msg = ""; - recordingPathChanged && (msg += Globalize.translate("RecordingPathChangeMessage")), msg && require(["alert"], function(alert) { - alert(msg) - }) + + if (recordingPathChanged) { + msg += Globalize.translate("RecordingPathChangeMessage"); + } + + if (msg) { + require(["alert"], function (alert) { + alert(msg); + }); + } } - $(document).on("pageinit", "#liveTvSettingsPage", function() { + + $(document).on("pageinit", "#liveTvSettingsPage", function () { var page = this; - $(".liveTvSettingsForm").off("submit", onSubmit).on("submit", onSubmit), $("#btnSelectRecordingPath", page).on("click.selectDirectory", function() { - require(["directorybrowser"], function(directoryBrowser) { - var picker = new directoryBrowser; + $(".liveTvSettingsForm").off("submit", onSubmit).on("submit", onSubmit); + $("#btnSelectRecordingPath", page).on("click.selectDirectory", function () { + require(["directorybrowser"], function (directoryBrowser) { + var picker = new directoryBrowser(); picker.show({ - callback: function(path) { - path && $("#txtRecordingPath", page).val(path), picker.close() + callback: function (path) { + if (path) { + $("#txtRecordingPath", page).val(path); + } + + picker.close(); }, - validateWriteable: !0 - }) - }) - }), $("#btnSelectMovieRecordingPath", page).on("click.selectDirectory", function() { - require(["directorybrowser"], function(directoryBrowser) { - var picker = new directoryBrowser; + validateWriteable: true + }); + }); + }); + $("#btnSelectMovieRecordingPath", page).on("click.selectDirectory", function () { + require(["directorybrowser"], function (directoryBrowser) { + var picker = new directoryBrowser(); picker.show({ - callback: function(path) { - path && $("#txtMovieRecordingPath", page).val(path), picker.close() + callback: function (path) { + if (path) { + $("#txtMovieRecordingPath", page).val(path); + } + + picker.close(); }, - validateWriteable: !0 - }) - }) - }), $("#btnSelectSeriesRecordingPath", page).on("click.selectDirectory", function() { - require(["directorybrowser"], function(directoryBrowser) { - var picker = new directoryBrowser; + validateWriteable: true + }); + }); + }); + $("#btnSelectSeriesRecordingPath", page).on("click.selectDirectory", function () { + require(["directorybrowser"], function (directoryBrowser) { + var picker = new directoryBrowser(); picker.show({ - callback: function(path) { - path && $("#txtSeriesRecordingPath", page).val(path), picker.close() + callback: function (path) { + if (path) { + $("#txtSeriesRecordingPath", page).val(path); + } + + picker.close(); }, - validateWriteable: !0 - }) - }) - }), $("#btnSelectPostProcessorPath", page).on("click.selectDirectory", function() { - require(["directorybrowser"], function(directoryBrowser) { - var picker = new directoryBrowser; + validateWriteable: true + }); + }); + }); + $("#btnSelectPostProcessorPath", page).on("click.selectDirectory", function () { + require(["directorybrowser"], function (directoryBrowser) { + var picker = new directoryBrowser(); picker.show({ - includeFiles: !0, - callback: function(path) { - path && $("#txtPostProcessor", page).val(path), picker.close() + includeFiles: true, + callback: function (path) { + if (path) { + $("#txtPostProcessor", page).val(path); + } + + picker.close(); } - }) - }) - }) - }).on("pageshow", "#liveTvSettingsPage", function() { + }); + }); + }); + }).on("pageshow", "#liveTvSettingsPage", function () { loading.show(); var page = this; - ApiClient.getNamedConfiguration("livetv").then(function(config) { - loadPage(page, config) - }) - }) -}); \ No newline at end of file + ApiClient.getNamedConfiguration("livetv").then(function (config) { + loadPage(page, config); + }); + }); +}); diff --git a/src/controllers/livetvstatus.js b/src/controllers/livetvstatus.js index d268be2991..03cad1a907 100644 --- a/src/controllers/livetvstatus.js +++ b/src/controllers/livetvstatus.js @@ -1,42 +1,75 @@ -define(["jQuery", "globalize", "scripts/taskbutton", "dom", "libraryMenu", "layoutManager", "loading", "listViewStyle", "flexStyles", "emby-itemscontainer", "cardStyle", "material-icons", "emby-button"], function($, globalize, taskButton, dom, libraryMenu, layoutManager, loading) { +define(["jQuery", "globalize", "scripts/taskbutton", "dom", "libraryMenu", "layoutManager", "loading", "listViewStyle", "flexStyles", "emby-itemscontainer", "cardStyle", "material-icons", "emby-button"], function ($, globalize, taskButton, dom, libraryMenu, layoutManager, loading) { "use strict"; function getDeviceHtml(device) { - var padderClass, html = "", - cssClass = "card scalableCard", - cardBoxCssClass = "cardBox visualCardBox"; - return cssClass += " backdropCard backdropCard-scalable", padderClass = "cardPadder-backdrop", layoutManager.tv && (cssClass += " card-focusscale", cardBoxCssClass += " cardBox-focustransform"), cardBoxCssClass += " card-focuscontent", html += '
            ', html += '
            ', html += '
            ', html += '
            ', html += '
            ', html += '
            dvr
            ', html += "
            ", html += "
            ", html += '
            ', html += '', html += '
            ' + (device.FriendlyName || getTunerName(device.Type)) + "
            ", html += '
            ', html += device.Url || " ", html += "
            ", html += "
            ", html += "
            ", html += "
            " + var padderClass; + var html = ""; + var cssClass = "card scalableCard"; + var cardBoxCssClass = "cardBox visualCardBox"; + cssClass += " backdropCard backdropCard-scalable"; + padderClass = "cardPadder-backdrop"; + + if (layoutManager.tv) { + cssClass += " card-focusscale"; + cardBoxCssClass += " cardBox-focustransform"; + } + + cardBoxCssClass += " card-focuscontent"; + html += '
            '; + html += '
            '; + html += '
            '; + html += '
            '; + html += '
            '; + html += '
            dvr
            '; + html += "
            "; + html += "
            "; + html += '
            '; + html += ''; + html += '
            ' + (device.FriendlyName || getTunerName(device.Type)) + "
            "; + html += '
            '; + html += device.Url || " "; + html += "
            "; + html += "
            "; + html += "
            "; + return html += "
            "; } function renderDevices(page, devices) { var html = devices.map(getDeviceHtml).join(""); - page.querySelector(".devicesList").innerHTML = html + page.querySelector(".devicesList").innerHTML = html; } function deleteDevice(page, id) { var message = globalize.translate("MessageConfirmDeleteTunerDevice"); - require(["confirm"], function(confirm) { - confirm(message, globalize.translate("HeaderDeleteDevice")).then(function() { - loading.show(), ApiClient.ajax({ + + require(["confirm"], function (confirm) { + confirm(message, globalize.translate("HeaderDeleteDevice")).then(function () { + loading.show(); + ApiClient.ajax({ type: "DELETE", url: ApiClient.getUrl("LiveTv/TunerHosts", { Id: id }) - }).then(function() { - reload(page) - }) - }) - }) + }).then(function () { + reload(page); + }); + }); + }); } function reload(page) { - loading.show(), ApiClient.getNamedConfiguration("livetv").then(function(config) { - renderDevices(page, config.TunerHosts), renderProviders(page, config.ListingProviders) - }), loading.hide() + loading.show(); + ApiClient.getNamedConfiguration("livetv").then(function (config) { + renderDevices(page, config.TunerHosts); + renderProviders(page, config.ListingProviders); + }); + loading.hide(); } function submitAddDeviceForm(page) { - page.querySelector(".dlgAddDevice").close(), loading.show(), ApiClient.ajax({ + page.querySelector(".dlgAddDevice").close(); + loading.show(); + ApiClient.ajax({ type: "POST", url: ApiClient.getUrl("LiveTv/TunerHosts"), data: JSON.stringify({ @@ -44,30 +77,47 @@ define(["jQuery", "globalize", "scripts/taskbutton", "dom", "libraryMenu", "layo Url: $("#txtDevicePath", page).val() }), contentType: "application/json" - }).then(function() { - reload(page) - }, function() { + }).then(function () { + reload(page); + }, function () { Dashboard.alert({ message: globalize.translate("ErrorAddingTunerDevice") - }) - }) + }); + }); } function renderProviders(page, providers) { var html = ""; + if (providers.length) { html += '
            '; + for (var i = 0, length = providers.length; i < length; i++) { var provider = providers[i]; - html += '" + html += '"; } - html += "
            " + + html += "
"; } + var elem = $(".providerList", page).html(html); - $(".btnOptions", elem).on("click", function() { + $(".btnOptions", elem).on("click", function () { var id = this.getAttribute("data-id"); - showProviderOptions(page, id, this) - }) + showProviderOptions(page, id, this); + }); } function showProviderOptions(page, providerId, button) { @@ -75,64 +125,74 @@ define(["jQuery", "globalize", "scripts/taskbutton", "dom", "libraryMenu", "layo items.push({ name: globalize.translate("ButtonDelete"), id: "delete" - }), items.push({ + }); + items.push({ name: globalize.translate("MapChannels"), id: "map" - }), require(["actionsheet"], function(actionsheet) { + }); + + require(["actionsheet"], function (actionsheet) { actionsheet.show({ items: items, positionTo: button - }).then(function(id) { + }).then(function (id) { switch (id) { case "delete": deleteProvider(page, providerId); break; + case "map": - mapChannels(page, providerId) + mapChannels(page, providerId); } - }) - }) + }); + }); } function mapChannels(page, providerId) { - require(["components/channelmapper/channelmapper"], function(channelmapper) { + require(["components/channelmapper/channelmapper"], function (channelmapper) { new channelmapper({ serverId: ApiClient.serverInfo().Id, providerId: providerId - }).show() - }) + }).show(); + }); } function deleteProvider(page, id) { var message = globalize.translate("MessageConfirmDeleteGuideProvider"); - require(["confirm"], function(confirm) { - confirm(message, globalize.translate("HeaderDeleteProvider")).then(function() { - loading.show(), ApiClient.ajax({ + + require(["confirm"], function (confirm) { + confirm(message, globalize.translate("HeaderDeleteProvider")).then(function () { + loading.show(); + ApiClient.ajax({ type: "DELETE", url: ApiClient.getUrl("LiveTv/ListingProviders", { Id: id }) - }).then(function() { - reload(page) - }, function() { - reload(page) - }) - }) - }) + }).then(function () { + reload(page); + }, function () { + reload(page); + }); + }); + }); } function getTunerName(providerId) { switch (providerId = providerId.toLowerCase()) { case "m3u": return "M3U"; + case "hdhomerun": return "HDHomerun"; + case "hauppauge": return "Hauppauge"; + case "satip": return "DVB"; + default: - return "Unknown" + return "Unknown"; } } @@ -140,12 +200,15 @@ define(["jQuery", "globalize", "scripts/taskbutton", "dom", "libraryMenu", "layo switch (providerId = providerId.toLowerCase()) { case "schedulesdirect": return "Schedules Direct"; + case "xmltv": return "Xml TV"; + case "emby": return "Emby Guide"; + default: - return "Unknown" + return "Unknown"; } } @@ -153,10 +216,12 @@ define(["jQuery", "globalize", "scripts/taskbutton", "dom", "libraryMenu", "layo switch (providerId = providerId.toLowerCase()) { case "xmltv": return "livetvguideprovider.html?type=xmltv"; + case "schedulesdirect": return "livetvguideprovider.html?type=schedulesdirect"; + case "emby": - return "livetvguideprovider.html?type=emby" + return "livetvguideprovider.html?type=emby"; } } @@ -165,22 +230,25 @@ define(["jQuery", "globalize", "scripts/taskbutton", "dom", "libraryMenu", "layo menuItems.push({ name: "Schedules Direct", id: "SchedulesDirect" - }), menuItems.push({ + }); + menuItems.push({ name: "Xml TV", id: "xmltv" - }), require(["actionsheet"], function(actionsheet) { + }); + + require(["actionsheet"], function (actionsheet) { actionsheet.show({ items: menuItems, positionTo: button, - callback: function(id) { - Dashboard.navigate(getProviderConfigurationUrl(id)) + callback: function (id) { + Dashboard.navigate(getProviderConfigurationUrl(id)); } - }) - }) + }); + }); } function addDevice(button) { - Dashboard.navigate("livetvtuner.html") + Dashboard.navigate("livetvtuner.html"); } function showDeviceMenu(button, tunerDeviceId) { @@ -188,57 +256,73 @@ define(["jQuery", "globalize", "scripts/taskbutton", "dom", "libraryMenu", "layo items.push({ name: globalize.translate("ButtonDelete"), id: "delete" - }), items.push({ + }); + items.push({ name: globalize.translate("ButtonEdit"), id: "edit" - }), require(["actionsheet"], function(actionsheet) { + }); + + require(["actionsheet"], function (actionsheet) { actionsheet.show({ items: items, positionTo: button - }).then(function(id) { + }).then(function (id) { switch (id) { case "delete": deleteDevice(dom.parentWithClass(button, "page"), tunerDeviceId); break; + case "edit": - Dashboard.navigate("livetvtuner.html?id=" + tunerDeviceId) + Dashboard.navigate("livetvtuner.html?id=" + tunerDeviceId); } - }) - }) + }); + }); } function onDevicesListClick(e) { var card = dom.parentWithClass(e.target, "card"); + if (card) { - var id = card.getAttribute("data-id"), - btnCardOptions = dom.parentWithClass(e.target, "btnCardOptions"); - btnCardOptions ? showDeviceMenu(btnCardOptions, id) : Dashboard.navigate("livetvtuner.html?id=" + id) + var id = card.getAttribute("data-id"); + var btnCardOptions = dom.parentWithClass(e.target, "btnCardOptions"); + + if (btnCardOptions) { + showDeviceMenu(btnCardOptions, id); + } else { + Dashboard.navigate("livetvtuner.html?id=" + id); + } } } - $(document).on("pageinit", "#liveTvStatusPage", function() { + + $(document).on("pageinit", "#liveTvStatusPage", function () { var page = this; - $(".btnAddDevice", page).on("click", function() { - addDevice(this) - }), $(".formAddDevice", page).on("submit", function() { - return submitAddDeviceForm(page), !1 - }), $(".btnAddProvider", page).on("click", function() { - addProvider(this) - }), page.querySelector(".devicesList").addEventListener("click", onDevicesListClick) - }).on("pageshow", "#liveTvStatusPage", function() { + $(".btnAddDevice", page).on("click", function () { + addDevice(this); + }); + $(".formAddDevice", page).on("submit", function () { + submitAddDeviceForm(page); + return false; + }); + $(".btnAddProvider", page).on("click", function () { + addProvider(this); + }); + page.querySelector(".devicesList").addEventListener("click", onDevicesListClick); + }).on("pageshow", "#liveTvStatusPage", function () { var page = this; - reload(page), taskButton({ + reload(page); + taskButton({ mode: "on", progressElem: page.querySelector(".refreshGuideProgress"), taskKey: "RefreshGuide", button: page.querySelector(".btnRefresh") - }) - }).on("pagehide", "#liveTvStatusPage", function() { + }); + }).on("pagehide", "#liveTvStatusPage", function () { var page = this; taskButton({ mode: "off", progressElem: page.querySelector(".refreshGuideProgress"), taskKey: "RefreshGuide", button: page.querySelector(".btnRefresh") - }) - }) + }); + }); }); diff --git a/src/controllers/livetvtuner.js b/src/controllers/livetvtuner.js index 43082e6844..55a86d4be7 100644 --- a/src/controllers/livetvtuner.js +++ b/src/controllers/livetvtuner.js @@ -1,4 +1,4 @@ -define(["globalize", "loading", "libraryMenu", "dom", "emby-input", "emby-button", "emby-checkbox", "emby-select"], function(globalize, loading, libraryMenu, dom) { +define(["globalize", "loading", "libraryMenu", "dom", "emby-input", "emby-button", "emby-checkbox", "emby-select"], function (globalize, loading, libraryMenu, dom) { "use strict"; function isM3uVariant(type) { @@ -6,17 +6,16 @@ define(["globalize", "loading", "libraryMenu", "dom", "emby-input", "emby-button } function fillTypes(view, currentId) { - return ApiClient.getJSON(ApiClient.getUrl("LiveTv/TunerHosts/Types")).then(function(types) { + return ApiClient.getJSON(ApiClient.getUrl("LiveTv/TunerHosts/Types")).then(function (types) { var selectType = view.querySelector(".selectType"); var html = ""; - html += types.map(function(tuner) { + html += types.map(function (tuner) { return '"; }).join(""); html += '"; selectType.innerHTML = html; - selectType.disabled = null != currentId; selectType.value = ""; onTypeChange.call(selectType); @@ -27,9 +26,10 @@ define(["globalize", "loading", "libraryMenu", "dom", "emby-input", "emby-button view.querySelector(".txtDevicePath").value = ""; view.querySelector(".chkFavorite").checked = false; view.querySelector(".txtDevicePath").value = ""; + if (providerId) { - ApiClient.getNamedConfiguration("livetv").then(function(config) { - var info = config.TunerHosts.filter(function(i) { + ApiClient.getNamedConfiguration("livetv").then(function (config) { + var info = config.TunerHosts.filter(function (i) { return i.Id === providerId; })[0]; fillTunerHostInfo(view, info); @@ -40,9 +40,11 @@ define(["globalize", "loading", "libraryMenu", "dom", "emby-input", "emby-button function fillTunerHostInfo(view, info) { var selectType = view.querySelector(".selectType"); var type = info.Type || ""; + if (info.Source && isM3uVariant(info.Source)) { type = info.Source; } + selectType.value = type; onTypeChange.call(selectType); view.querySelector(".txtDevicePath").value = info.Url || ""; @@ -68,76 +70,164 @@ define(["globalize", "loading", "libraryMenu", "dom", "emby-input", "emby-button AllowHWTranscoding: page.querySelector(".chkTranscode").checked, EnableStreamLooping: page.querySelector(".chkStreamLoop").checked }; - isM3uVariant(info.Type) && (info.Source = info.Type, info.Type = "m3u"); + + if (isM3uVariant(info.Type)) { + info.Source = info.Type; + info.Type = "m3u"; + } + var id = getParameterByName("id"); - id && (info.Id = id); + + if (id) { + info.Id = id; + } + info.Id; ApiClient.ajax({ type: "POST", url: ApiClient.getUrl("LiveTv/TunerHosts"), data: JSON.stringify(info), contentType: "application/json" - }).then(function(result) { - Dashboard.processServerConfigurationUpdateResult(), Dashboard.navigate("livetvstatus.html") - }, function() { - loading.hide(), Dashboard.alert({ + }).then(function (result) { + Dashboard.processServerConfigurationUpdateResult(); + Dashboard.navigate("livetvstatus.html"); + }, function () { + loading.hide(); + Dashboard.alert({ message: globalize.translate("ErrorSavingTvProvider") - }) - }) + }); + }); } function getRequirePromise(deps) { - return new Promise(function(resolve, reject) { - require(deps, resolve) - }) + return new Promise(function (resolve, reject) { + require(deps, resolve); + }); } function getDetectedDevice() { - return getRequirePromise(["tunerPicker"]).then(function(tunerPicker) { - return (new tunerPicker).show({ + return getRequirePromise(["tunerPicker"]).then(function (tunerPicker) { + return new tunerPicker().show({ serverId: ApiClient.serverId() - }) - }) + }); + }); } function onTypeChange() { - var value = this.value, - view = dom.parentWithClass(this, "page"), - mayIncludeUnsupportedDrmChannels = "hdhomerun" === value, - supportsTranscoding = "hdhomerun" === value, - supportsFavorites = "hdhomerun" === value, - supportsTunerIpAddress = "hdhomerun" === value, - supportsTunerFileOrUrl = "m3u" === value, - supportsStreamLooping = "m3u" === value, - supportsTunerCount = "m3u" === value, - supportsUserAgent = "m3u" === value, - suppportsSubmit = "other" !== value, - supportsSelectablePath = supportsTunerFileOrUrl, - txtDevicePath = view.querySelector(".txtDevicePath"); - supportsTunerIpAddress ? (txtDevicePath.label(globalize.translate("LabelTunerIpAddress")), view.querySelector(".fldPath").classList.remove("hide")) : supportsTunerFileOrUrl ? (txtDevicePath.label(globalize.translate("LabelFileOrUrl")), view.querySelector(".fldPath").classList.remove("hide")) : view.querySelector(".fldPath").classList.add("hide"), supportsSelectablePath ? (view.querySelector(".btnSelectPath").classList.remove("hide"), view.querySelector(".txtDevicePath").setAttribute("required", "required")) : (view.querySelector(".btnSelectPath").classList.add("hide"), view.querySelector(".txtDevicePath").removeAttribute("required")), supportsUserAgent ? view.querySelector(".fldUserAgent").classList.remove("hide") : view.querySelector(".fldUserAgent").classList.add("hide"), supportsFavorites ? view.querySelector(".fldFavorites").classList.remove("hide") : view.querySelector(".fldFavorites").classList.add("hide"), supportsTranscoding ? view.querySelector(".fldTranscode").classList.remove("hide") : view.querySelector(".fldTranscode").classList.add("hide"), supportsStreamLooping ? view.querySelector(".fldStreamLoop").classList.remove("hide") : view.querySelector(".fldStreamLoop").classList.add("hide"), supportsTunerCount ? (view.querySelector(".fldTunerCount").classList.remove("hide"), view.querySelector(".txtTunerCount").setAttribute("required", "required")) : (view.querySelector(".fldTunerCount").classList.add("hide"), view.querySelector(".txtTunerCount").removeAttribute("required")), mayIncludeUnsupportedDrmChannels ? view.querySelector(".drmMessage").classList.remove("hide") : view.querySelector(".drmMessage").classList.add("hide"), suppportsSubmit ? view.querySelector(".button-submit").classList.remove("hide") : view.querySelector(".button-submit").classList.add("hide") + var value = this.value; + var view = dom.parentWithClass(this, "page"); + var mayIncludeUnsupportedDrmChannels = "hdhomerun" === value; + var supportsTranscoding = "hdhomerun" === value; + var supportsFavorites = "hdhomerun" === value; + var supportsTunerIpAddress = "hdhomerun" === value; + var supportsTunerFileOrUrl = "m3u" === value; + var supportsStreamLooping = "m3u" === value; + var supportsTunerCount = "m3u" === value; + var supportsUserAgent = "m3u" === value; + var suppportsSubmit = "other" !== value; + var supportsSelectablePath = supportsTunerFileOrUrl; + var txtDevicePath = view.querySelector(".txtDevicePath"); + + if (supportsTunerIpAddress) { + txtDevicePath.label(globalize.translate("LabelTunerIpAddress")); + view.querySelector(".fldPath").classList.remove("hide"); + } else if (supportsTunerFileOrUrl) { + txtDevicePath.label(globalize.translate("LabelFileOrUrl")); + view.querySelector(".fldPath").classList.remove("hide"); + } else { + view.querySelector(".fldPath").classList.add("hide"); + } + + if (supportsSelectablePath) { + view.querySelector(".btnSelectPath").classList.remove("hide"); + view.querySelector(".txtDevicePath").setAttribute("required", "required"); + } else { + view.querySelector(".btnSelectPath").classList.add("hide"); + view.querySelector(".txtDevicePath").removeAttribute("required"); + } + + if (supportsUserAgent) { + view.querySelector(".fldUserAgent").classList.remove("hide"); + } else { + view.querySelector(".fldUserAgent").classList.add("hide"); + } + + if (supportsFavorites) { + view.querySelector(".fldFavorites").classList.remove("hide"); + } else { + view.querySelector(".fldFavorites").classList.add("hide"); + } + + if (supportsTranscoding) { + view.querySelector(".fldTranscode").classList.remove("hide"); + } else { + view.querySelector(".fldTranscode").classList.add("hide"); + } + + if (supportsStreamLooping) { + view.querySelector(".fldStreamLoop").classList.remove("hide"); + } else { + view.querySelector(".fldStreamLoop").classList.add("hide"); + } + + if (supportsTunerCount) { + view.querySelector(".fldTunerCount").classList.remove("hide"); + view.querySelector(".txtTunerCount").setAttribute("required", "required"); + } else { + view.querySelector(".fldTunerCount").classList.add("hide"); + view.querySelector(".txtTunerCount").removeAttribute("required"); + } + + if (mayIncludeUnsupportedDrmChannels) { + view.querySelector(".drmMessage").classList.remove("hide"); + } else { + view.querySelector(".drmMessage").classList.add("hide"); + } + + if (suppportsSubmit) { + view.querySelector(".button-submit").classList.remove("hide"); + } else { + view.querySelector(".button-submit").classList.add("hide"); + } } - return function(view, params) { - params.id || view.querySelector(".btnDetect").classList.remove("hide"), view.addEventListener("viewshow", function() { + + return function (view, params) { + if (!params.id) { + view.querySelector(".btnDetect").classList.remove("hide"); + } + + view.addEventListener("viewshow", function () { var currentId = params.id; - fillTypes(view, currentId).then(function() { - reload(view, currentId) - }) - }), view.querySelector("form").addEventListener("submit", function(e) { - return submitForm(view), e.preventDefault(), e.stopPropagation(), !1 - }), view.querySelector(".selectType").addEventListener("change", onTypeChange), view.querySelector(".btnDetect").addEventListener("click", function() { - getDetectedDevice().then(function(info) { - fillTunerHostInfo(view, info) - }) - }), view.querySelector(".btnSelectPath").addEventListener("click", function() { - require(["directorybrowser"], function(directoryBrowser) { - var picker = new directoryBrowser; + fillTypes(view, currentId).then(function () { + reload(view, currentId); + }); + }); + view.querySelector("form").addEventListener("submit", function (e) { + submitForm(view); + e.preventDefault(); + e.stopPropagation(); + return false; + }); + view.querySelector(".selectType").addEventListener("change", onTypeChange); + view.querySelector(".btnDetect").addEventListener("click", function () { + getDetectedDevice().then(function (info) { + fillTunerHostInfo(view, info); + }); + }); + view.querySelector(".btnSelectPath").addEventListener("click", function () { + require(["directorybrowser"], function (directoryBrowser) { + var picker = new directoryBrowser(); picker.show({ - includeFiles: !0, - callback: function(path) { - path && (view.querySelector(".txtDevicePath").value = path), picker.close() + includeFiles: true, + callback: function (path) { + if (path) { + view.querySelector(".txtDevicePath").value = path; + } + + picker.close(); } - }) - }) - }) - } -}); \ No newline at end of file + }); + }); + }); + }; +}); diff --git a/src/controllers/metadatanfo.js b/src/controllers/metadatanfo.js index 1de17ae836..20049837dd 100644 --- a/src/controllers/metadatanfo.js +++ b/src/controllers/metadatanfo.js @@ -1,30 +1,45 @@ -define(["jQuery", "loading", "libraryMenu"], function($, loading, libraryMenu) { +define(["jQuery", "loading", "libraryMenu"], function ($, loading, libraryMenu) { "use strict"; function loadPage(page, config, users) { var html = '"; - html += users.map(function(user) { - return '" - }).join(""), $("#selectUser", page).html(html).val(config.UserId || ""), $("#selectReleaseDateFormat", page).val(config.ReleaseDateFormat), page.querySelector("#chkSaveImagePaths").checked = config.SaveImagePathsInNfo, page.querySelector("#chkEnablePathSubstitution").checked = config.EnablePathSubstitution, page.querySelector("#chkEnableExtraThumbs").checked = config.EnableExtraThumbsDuplication, loading.hide() + html += users.map(function (user) { + return '"; + }).join(""); + $("#selectUser", page).html(html).val(config.UserId || ""); + $("#selectReleaseDateFormat", page).val(config.ReleaseDateFormat); + page.querySelector("#chkSaveImagePaths").checked = config.SaveImagePathsInNfo; + page.querySelector("#chkEnablePathSubstitution").checked = config.EnablePathSubstitution; + page.querySelector("#chkEnableExtraThumbs").checked = config.EnableExtraThumbsDuplication; + loading.hide(); } function onSubmit() { loading.show(); var form = this; - return ApiClient.getNamedConfiguration(metadataKey).then(function(config) { - config.UserId = $("#selectUser", form).val() || null, config.ReleaseDateFormat = $("#selectReleaseDateFormat", form).val(), config.SaveImagePathsInNfo = form.querySelector("#chkSaveImagePaths").checked, config.EnablePathSubstitution = form.querySelector("#chkEnablePathSubstitution").checked, config.EnableExtraThumbsDuplication = form.querySelector("#chkEnableExtraThumbs").checked, ApiClient.updateNamedConfiguration(metadataKey, config).then(function() { - Dashboard.processServerConfigurationUpdateResult(), showConfirmMessage(config) - }) - }), !1 + ApiClient.getNamedConfiguration(metadataKey).then(function (config) { + config.UserId = $("#selectUser", form).val() || null; + config.ReleaseDateFormat = $("#selectReleaseDateFormat", form).val(); + config.SaveImagePathsInNfo = form.querySelector("#chkSaveImagePaths").checked; + config.EnablePathSubstitution = form.querySelector("#chkEnablePathSubstitution").checked; + config.EnableExtraThumbsDuplication = form.querySelector("#chkEnableExtraThumbs").checked; + ApiClient.updateNamedConfiguration(metadataKey, config).then(function () { + Dashboard.processServerConfigurationUpdateResult(); + showConfirmMessage(config); + }); + }); + return false; } function showConfirmMessage(config) { var msg = []; - msg.push(Globalize.translate("MetadataSettingChangeHelp")), require(["alert"], function(alert) { + msg.push(Globalize.translate("MetadataSettingChangeHelp")); + + require(["alert"], function (alert) { alert({ text: msg.join("

") - }) - }) + }); + }); } function getTabs() { @@ -40,19 +55,20 @@ define(["jQuery", "loading", "libraryMenu"], function($, loading, libraryMenu) { }, { href: "metadatanfo.html", name: Globalize.translate("TabNfoSettings") - }] + }]; } var metadataKey = "xbmcmetadata"; - $(document).on("pageinit", "#metadataNfoPage", function() { - $(".metadataNfoForm").off("submit", onSubmit).on("submit", onSubmit) - }).on("pageshow", "#metadataNfoPage", function() { - libraryMenu.setTabs("metadata", 3, getTabs), loading.show(); - var page = this, - promise1 = ApiClient.getUsers(), - promise2 = ApiClient.getNamedConfiguration(metadataKey); - Promise.all([promise1, promise2]).then(function(responses) { - loadPage(page, responses[1], responses[0]) - }) - }) -}); \ No newline at end of file + $(document).on("pageinit", "#metadataNfoPage", function () { + $(".metadataNfoForm").off("submit", onSubmit).on("submit", onSubmit); + }).on("pageshow", "#metadataNfoPage", function () { + libraryMenu.setTabs("metadata", 3, getTabs); + loading.show(); + var page = this; + var promise1 = ApiClient.getUsers(); + var promise2 = ApiClient.getNamedConfiguration(metadataKey); + Promise.all([promise1, promise2]).then(function (responses) { + loadPage(page, responses[1], responses[0]); + }); + }); +}); diff --git a/src/controllers/movies/moviecollections.js b/src/controllers/movies/moviecollections.js index 1e83f11f3c..d5bd96d349 100644 --- a/src/controllers/movies/moviecollections.js +++ b/src/controllers/movies/moviecollections.js @@ -1,9 +1,11 @@ -define(["loading", "events", "libraryBrowser", "imageLoader", "listView", "cardBuilder", "apphost", "emby-itemscontainer"], function(loading, events, libraryBrowser, imageLoader, listView, cardBuilder, appHost) { +define(["loading", "events", "libraryBrowser", "imageLoader", "listView", "cardBuilder", "apphost", "emby-itemscontainer"], function (loading, events, libraryBrowser, imageLoader, listView, cardBuilder, appHost) { "use strict"; - return function(view, params, tabContent) { + + return function (view, params, tabContent) { function getPageData(context) { - var key = getSavedQueryKey(context), - pageData = data[key]; + var key = getSavedQueryKey(context); + var pageData = data[key]; + if (!pageData) { pageData = data[key] = { query: { @@ -22,153 +24,223 @@ define(["loading", "events", "libraryBrowser", "imageLoader", "listView", "cardB pageData.query.ParentId = params.topParentId; libraryBrowser.loadSavedQueryValues(key, pageData.query); } + return pageData; } function getQuery(context) { - return getPageData(context).query + return getPageData(context).query; } function getSavedQueryKey(context) { - return context.savedQueryKey || (context.savedQueryKey = libraryBrowser.getSavedQueryKey("moviecollections")), context.savedQueryKey + if (!context.savedQueryKey) { + context.savedQueryKey = libraryBrowser.getSavedQueryKey("moviecollections"); + } + + return context.savedQueryKey; } function onViewStyleChange() { - var viewStyle = self.getCurrentViewStyle(), - itemsContainer = tabContent.querySelector(".itemsContainer"); - "List" == viewStyle ? (itemsContainer.classList.add("vertical-list"), itemsContainer.classList.remove("vertical-wrap")) : (itemsContainer.classList.remove("vertical-list"), itemsContainer.classList.add("vertical-wrap")), itemsContainer.innerHTML = "" + var viewStyle = self.getCurrentViewStyle(); + var itemsContainer = tabContent.querySelector(".itemsContainer"); + + 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.innerHTML = ""; } function reloadItems(page) { loading.show(); isLoading = true; var query = getQuery(page); - ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function(result) { + ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function (result) { function onNextPageClick() { - if (isLoading) return; - query.StartIndex += query.Limit, reloadItems(tabContent) + if (isLoading) { + return; + } + + query.StartIndex += query.Limit; + reloadItems(tabContent); } function onPreviousPageClick() { - if (isLoading) return; - query.StartIndex -= query.Limit, reloadItems(tabContent) + if (isLoading) { + return; + } + + query.StartIndex -= query.Limit; + reloadItems(tabContent); } + window.scrollTo(0, 0); - var html, pagingHtml = libraryBrowser.getQueryPagingHtml({ - startIndex: query.StartIndex, - limit: query.Limit, - totalRecordCount: result.TotalRecordCount, - showLimit: !1, - updatePageSizeSetting: !1, - addLayoutButton: !1, - sortButton: !1, - filterButton: !1 - }), - viewStyle = self.getCurrentViewStyle(); - html = "Thumb" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "backdrop", - preferThumb: !0, - context: "movies", - overlayPlayButton: !0, - centerText: !0, - showTitle: !0 - }) : "ThumbCard" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "backdrop", - preferThumb: !0, - context: "movies", - lazy: !0, - cardLayout: !0, - showTitle: !0 - }) : "Banner" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "banner", - preferBanner: !0, - context: "movies", - lazy: !0 - }) : "List" == viewStyle ? listView.getListViewHtml({ - items: result.Items, - context: "movies", - sortBy: query.SortBy - }) : "PosterCard" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "auto", - context: "movies", - showTitle: !0, - centerText: !1, - cardLayout: !0 - }) : cardBuilder.getCardsHtml({ - items: result.Items, - shape: "auto", - context: "movies", - centerText: !0, - overlayPlayButton: !0, - showTitle: !0 + var html; + var pagingHtml = libraryBrowser.getQueryPagingHtml({ + startIndex: query.StartIndex, + limit: query.Limit, + totalRecordCount: result.TotalRecordCount, + showLimit: false, + updatePageSizeSetting: false, + addLayoutButton: false, + sortButton: false, + filterButton: false }); - var i, length, elems = tabContent.querySelectorAll(".paging"); - for (i = 0, length = elems.length; i < length; i++) elems[i].innerHTML = pagingHtml; - for (elems = tabContent.querySelectorAll(".btnNextPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onNextPageClick); - for (elems = tabContent.querySelectorAll(".btnPreviousPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onPreviousPageClick); - result.Items.length || (html = '

' + Globalize.translate("MessageNoCollectionsAvailable") + "

"); + var viewStyle = self.getCurrentViewStyle(); + if (viewStyle == "Thumb") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "backdrop", + preferThumb: true, + context: "movies", + overlayPlayButton: true, + centerText: true, + showTitle: true + }); + } else if (viewStyle == "ThumbCard") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "backdrop", + preferThumb: true, + context: "movies", + lazy: true, + cardLayout: true, + showTitle: true + }); + } else if (viewStyle == "Banner") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "banner", + preferBanner: true, + context: "movies", + lazy: true + }); + } else if (viewStyle == "List") { + html = listView.getListViewHtml({ + items: result.Items, + context: "movies", + sortBy: query.SortBy + }); + } else if (viewStyle == "PosterCard") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "auto", + context: "movies", + showTitle: true, + centerText: false, + cardLayout: true + }); + } else { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "auto", + context: "movies", + centerText: true, + overlayPlayButton: true, + showTitle: true + }); + } + var i; + var length; + var elems = tabContent.querySelectorAll(".paging"); + + for (i = 0, length = elems.length; i < length; i++) { + elems[i].innerHTML = pagingHtml; + } + + elems = tabContent.querySelectorAll(".btnNextPage"); + for (i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener("click", onNextPageClick); + } + + elems = tabContent.querySelectorAll(".btnPreviousPage"); + for (i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener("click", onPreviousPageClick); + } + + if (!result.Items.length) { + html = '

' + Globalize.translate("MessageNoCollectionsAvailable") + "

"; + } + var itemsContainer = tabContent.querySelector(".itemsContainer"); itemsContainer.innerHTML = html; imageLoader.lazyChildren(itemsContainer); libraryBrowser.saveQueryValues(getSavedQueryKey(page), query); loading.hide(); isLoading = false; - }) + }); } - var self = this, - pageSize = 100, - data = {}, - isLoading = false; - self.getCurrentViewStyle = function() { - return getPageData(tabContent).view - }, - function(tabContent) { - tabContent.querySelector(".btnSort").addEventListener("click", function(e) { - libraryBrowser.showSortMenu({ - items: [{ - name: Globalize.translate("OptionNameSort"), - id: "SortName" - }, { - name: Globalize.translate("OptionImdbRating"), - id: "CommunityRating,SortName" - }, { - name: Globalize.translate("OptionDateAdded"), - id: "DateCreated,SortName" - }, { - name: Globalize.translate("OptionParentalRating"), - id: "OfficialRating,SortName" - }, { - name: Globalize.translate("OptionReleaseDate"), - id: "PremiereDate,SortName" - }], - callback: function() { - getQuery(tabContent).StartIndex = 0, reloadItems(tabContent) - }, - query: getQuery(tabContent), - button: e.target - }) + + var self = this; + var pageSize = 100; + var data = {}; + var isLoading = false; + + self.getCurrentViewStyle = function () { + return getPageData(tabContent).view; + }; + + function initPage(tabContent) { + tabContent.querySelector(".btnSort").addEventListener("click", function (e) { + libraryBrowser.showSortMenu({ + items: [{ + name: Globalize.translate("OptionNameSort"), + id: "SortName" + }, { + name: Globalize.translate("OptionImdbRating"), + id: "CommunityRating,SortName" + }, { + name: Globalize.translate("OptionDateAdded"), + id: "DateCreated,SortName" + }, { + name: Globalize.translate("OptionParentalRating"), + id: "OfficialRating,SortName" + }, { + name: Globalize.translate("OptionReleaseDate"), + id: "PremiereDate,SortName" + }], + callback: function () { + getQuery(tabContent).StartIndex = 0; + reloadItems(tabContent); + }, + query: getQuery(tabContent), + button: e.target }); - var btnSelectView = tabContent.querySelector(".btnSelectView"); - btnSelectView.addEventListener("click", function(e) { - libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), "List,Poster,PosterCard,Thumb,ThumbCard".split(",")) - }), btnSelectView.addEventListener("layoutchange", function(e) { - var viewStyle = e.detail.viewStyle; - getPageData(tabContent).view = viewStyle, libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle), getQuery(tabContent).StartIndex = 0, onViewStyleChange(), reloadItems(tabContent) - }), tabContent.querySelector(".btnNewCollection").addEventListener("click", function() { - require(["collectionEditor"], function(collectionEditor) { - var serverId = ApiClient.serverInfo().Id; - (new collectionEditor).show({ - items: [], - serverId: serverId - }) - }) - }) - }(tabContent), onViewStyleChange(), self.renderTab = function() { - reloadItems(tabContent) - }, self.destroy = function() {} - } + }); + var btnSelectView = tabContent.querySelector(".btnSelectView"); + btnSelectView.addEventListener("click", function (e) { + libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), "List,Poster,PosterCard,Thumb,ThumbCard".split(",")); + }); + btnSelectView.addEventListener("layoutchange", function (e) { + var viewStyle = e.detail.viewStyle; + getPageData(tabContent).view = viewStyle; + libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle); + getQuery(tabContent).StartIndex = 0; + onViewStyleChange(); + reloadItems(tabContent); + }); + tabContent.querySelector(".btnNewCollection").addEventListener("click", function () { + require(["collectionEditor"], function (collectionEditor) { + var serverId = ApiClient.serverInfo().Id; + new collectionEditor().show({ + items: [], + serverId: serverId + }); + }); + }); + } + + initPage(tabContent); + onViewStyleChange(); + + self.renderTab = function () { + reloadItems(tabContent); + }; + + self.destroy = function () {}; + }; }); diff --git a/src/controllers/movies/moviegenres.js b/src/controllers/movies/moviegenres.js index 78fd601fd7..80197b01cc 100644 --- a/src/controllers/movies/moviegenres.js +++ b/src/controllers/movies/moviegenres.js @@ -1,139 +1,204 @@ -define(["layoutManager", "loading", "libraryBrowser", "cardBuilder", "lazyLoader", "apphost", "globalize", "appRouter", "dom", "emby-button"], function(layoutManager, loading, libraryBrowser, cardBuilder, lazyLoader, appHost, globalize, appRouter, dom) { +define(["layoutManager", "loading", "libraryBrowser", "cardBuilder", "lazyLoader", "apphost", "globalize", "appRouter", "dom", "emby-button"], function (layoutManager, loading, libraryBrowser, cardBuilder, lazyLoader, appHost, globalize, appRouter, dom) { "use strict"; - return function(view, params, tabContent) { + + return function (view, params, tabContent) { function getPageData() { - var key = getSavedQueryKey(), - pageData = data[key]; - return pageData || (pageData = data[key] = { - query: { - SortBy: "SortName", - SortOrder: "Ascending", - IncludeItemTypes: "Movie", - Recursive: !0, - EnableTotalRecordCount: !1 - }, - view: "Poster" - }, pageData.query.ParentId = params.topParentId, libraryBrowser.loadSavedQueryValues(key, pageData.query)), pageData + var key = getSavedQueryKey(); + var pageData = data[key]; + + if (!pageData) { + pageData = data[key] = { + query: { + SortBy: "SortName", + SortOrder: "Ascending", + IncludeItemTypes: "Movie", + Recursive: true, + EnableTotalRecordCount: false + }, + view: "Poster" + }; + pageData.query.ParentId = params.topParentId; + libraryBrowser.loadSavedQueryValues(key, pageData.query); + } + + return pageData; } function getQuery() { - return getPageData().query + return getPageData().query; } function getSavedQueryKey() { - return libraryBrowser.getSavedQueryKey("moviegenres") + return libraryBrowser.getSavedQueryKey("moviegenres"); } function getPromise() { loading.show(); var query = getQuery(); - return ApiClient.getGenres(ApiClient.getCurrentUserId(), query) + return ApiClient.getGenres(ApiClient.getCurrentUserId(), query); } function enableScrollX() { - return !layoutManager.desktop + return !layoutManager.desktop; } function getThumbShape() { - return enableScrollX() ? "overflowBackdrop" : "backdrop" + return enableScrollX() ? "overflowBackdrop" : "backdrop"; } function getPortraitShape() { - return enableScrollX() ? "overflowPortrait" : "portrait" + return enableScrollX() ? "overflowPortrait" : "portrait"; } function fillItemsContainer(elem) { - var id = elem.getAttribute("data-id"), - viewStyle = self.getCurrentViewStyle(), - limit = "Thumb" == viewStyle || "ThumbCard" == viewStyle ? 5 : 9; - enableScrollX() && (limit = 10); - var enableImageTypes = "Thumb" == viewStyle || "ThumbCard" == viewStyle ? "Primary,Backdrop,Thumb" : "Primary", - query = { - SortBy: "SortName", - SortOrder: "Ascending", - IncludeItemTypes: "Movie", - Recursive: !0, - Fields: "PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo", - ImageTypeLimit: 1, - EnableImageTypes: enableImageTypes, - Limit: limit, - GenreIds: id, - EnableTotalRecordCount: !1, - ParentId: params.topParentId - }; - ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function(result) { + var id = elem.getAttribute("data-id"); + var viewStyle = self.getCurrentViewStyle(); + var limit = "Thumb" == viewStyle || "ThumbCard" == viewStyle ? 5 : 9; + + if (enableScrollX()) { + limit = 10; + } + + var enableImageTypes = "Thumb" == viewStyle || "ThumbCard" == viewStyle ? "Primary,Backdrop,Thumb" : "Primary"; + var query = { + SortBy: "SortName", + SortOrder: "Ascending", + IncludeItemTypes: "Movie", + Recursive: true, + Fields: "PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo", + ImageTypeLimit: 1, + EnableImageTypes: enableImageTypes, + Limit: limit, + GenreIds: id, + EnableTotalRecordCount: false, + ParentId: params.topParentId + }; + ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function (result) { var supportsImageAnalysis = appHost.supports("imageanalysis"); - "Thumb" == viewStyle ? cardBuilder.buildCards(result.Items, { - itemsContainer: elem, - shape: getThumbShape(), - preferThumb: !0, - showTitle: !0, - scalable: !0, - centerText: !0, - overlayMoreButton: !0, - allowBottomPadding: !1 - }) : "ThumbCard" == viewStyle ? cardBuilder.buildCards(result.Items, { - itemsContainer: elem, - shape: getThumbShape(), - preferThumb: !0, - showTitle: !0, - scalable: !0, - centerText: !1, - cardLayout: !0, - showYear: !0 - }) : "PosterCard" == viewStyle ? cardBuilder.buildCards(result.Items, { - itemsContainer: elem, - shape: getPortraitShape(), - showTitle: !0, - scalable: !0, - centerText: !1, - cardLayout: !0, - showYear: !0 - }) : "Poster" == viewStyle && cardBuilder.buildCards(result.Items, { - itemsContainer: elem, - shape: getPortraitShape(), - scalable: !0, - overlayMoreButton: !0, - allowBottomPadding: !1 - }), result.Items.length >= query.Limit && tabContent.querySelector(".btnMoreFromGenre" + id + " i").classList.remove("hide") - }) + + if (viewStyle == "Thumb") { + cardBuilder.buildCards(result.Items, { + itemsContainer: elem, + shape: getThumbShape(), + preferThumb: true, + showTitle: true, + scalable: true, + centerText: true, + overlayMoreButton: true, + allowBottomPadding: false + }); + } else if (viewStyle == "ThumbCard") { + cardBuilder.buildCards(result.Items, { + itemsContainer: elem, + shape: getThumbShape(), + preferThumb: true, + showTitle: true, + scalable: true, + centerText: false, + cardLayout: true, + showYear: true + }); + } else if (viewStyle == "PosterCard") { + cardBuilder.buildCards(result.Items, { + itemsContainer: elem, + shape: getPortraitShape(), + showTitle: true, + scalable: true, + centerText: false, + cardLayout: true, + showYear: true + }); + } else if (viewStyle == "Poster") { + cardBuilder.buildCards(result.Items, { + itemsContainer: elem, + shape: getPortraitShape(), + scalable: true, + overlayMoreButton: true, + allowBottomPadding: false + }); + } + if (result.Items.length >= query.Limit) { + tabContent.querySelector(".btnMoreFromGenre" + id + " i").classList.remove("hide"); + } + }); } function reloadItems(context, promise) { var query = getQuery(); - promise.then(function(result) { - for (var elem = context.querySelector("#items"), html = "", items = result.Items, i = 0, length = items.length; i < length; i++) { + promise.then(function (result) { + var elem = context.querySelector("#items"); + var html = ""; + var items = result.Items; + + for (var i = 0, length = items.length; i < length; i++) { var item = items[i]; - if (html += '
', html += '", enableScrollX()) { + + html += '
'; + html += '"; + if (enableScrollX()) { var scrollXClass = "scrollX hiddenScrollX"; - layoutManager.tv && (scrollXClass += " smoothScrollX"), html += '
' - } else html += '
'; - html += "
", html += "
" + + if (layoutManager.tv) { + scrollXClass += "smoothScrollX"; + } + + html += '
'; + } else { + html += '
'; + } + + html += "
"; + html += "
"; } - elem.innerHTML = html, lazyLoader.lazyChildren(elem, fillItemsContainer), libraryBrowser.saveQueryValues(getSavedQueryKey(), query), loading.hide() - }) + + elem.innerHTML = html; + lazyLoader.lazyChildren(elem, fillItemsContainer); + libraryBrowser.saveQueryValues(getSavedQueryKey(), query); + loading.hide(); + }); } function fullyReload() { - self.preRender(), self.renderTab() + self.preRender(); + self.renderTab(); } - var self = this, - data = {}; - self.getViewStyles = function() { - return "Poster,PosterCard,Thumb,ThumbCard".split(",") - }, self.getCurrentViewStyle = function() { - return getPageData(tabContent).view - }, self.setCurrentViewStyle = function(viewStyle) { - getPageData(tabContent).view = viewStyle, libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle), fullyReload() - }, self.enableViewSelection = !0; + + var self = this; + var data = {}; + + self.getViewStyles = function () { + return "Poster,PosterCard,Thumb,ThumbCard".split(","); + }; + + self.getCurrentViewStyle = function () { + return getPageData(tabContent).view; + }; + + self.setCurrentViewStyle = function (viewStyle) { + getPageData(tabContent).view = viewStyle; + libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle); + fullyReload(); + }; + + self.enableViewSelection = true; var promise; - self.preRender = function() { - promise = getPromise() - }, self.renderTab = function() { - reloadItems(tabContent, promise) - } - } -}); \ No newline at end of file + + self.preRender = function () { + promise = getPromise(); + }; + + self.renderTab = function () { + reloadItems(tabContent, promise); + }; + }; +}); diff --git a/src/controllers/movies/movies.js b/src/controllers/movies/movies.js index e0a5947ca6..b4e30602fd 100644 --- a/src/controllers/movies/movies.js +++ b/src/controllers/movies/movies.js @@ -1,7 +1,7 @@ -define(["loading", "layoutManager", "userSettings", "events", "libraryBrowser", "alphaPicker", "listView", "cardBuilder", "emby-itemscontainer"], - function(loading, layoutManager, userSettings, events, libraryBrowser, alphaPicker, listView, cardBuilder) { +define(["loading", "layoutManager", "userSettings", "events", "libraryBrowser", "alphaPicker", "listView", "cardBuilder", "emby-itemscontainer"], function (loading, layoutManager, userSettings, events, libraryBrowser, alphaPicker, listView, cardBuilder) { "use strict"; - return function(view, params, tabContent, options) { + + return function (view, params, tabContent, options) { function onViewStyleChange() { if (self.getCurrentViewStyle() == "List") { itemsContainer.classList.add("vertical-list"); @@ -10,103 +10,141 @@ define(["loading", "layoutManager", "userSettings", "events", "libraryBrowser", itemsContainer.classList.remove("vertical-list"); itemsContainer.classList.add("vertical-wrap"); } + itemsContainer.innerHTML = ""; } function updateFilterControls() { - self.alphaPicker && self.alphaPicker.value(query.NameStartsWithOrGreater) + if (self.alphaPicker) { + self.alphaPicker.value(query.NameStartsWithOrGreater); + } } function fetchData() { isLoading = true; loading.show(); - return ApiClient.getItems(ApiClient.getCurrentUserId(), query) + return ApiClient.getItems(ApiClient.getCurrentUserId(), query); } function afterRefresh(result) { function onNextPageClick() { - if (isLoading) return; + if (isLoading) { + return; + } + query.StartIndex += query.Limit; itemsContainer.refreshItems(); } function onPreviousPageClick() { - if (isLoading) return; + if (isLoading) { + return; + } + query.StartIndex -= query.Limit; itemsContainer.refreshItems(); } + window.scrollTo(0, 0); updateFilterControls(); - var i, length, elems, pagingHtml = libraryBrowser.getQueryPagingHtml({ - startIndex: query.StartIndex, - limit: query.Limit, - totalRecordCount: result.TotalRecordCount, - showLimit: !1, - updatePageSizeSetting: !1, - addLayoutButton: !1, - sortButton: !1, - filterButton: !1 - }); - for (elems = tabContent.querySelectorAll(".paging"), i = 0, length = elems.length; i < length; i++) + var pagingHtml = libraryBrowser.getQueryPagingHtml({ + startIndex: query.StartIndex, + limit: query.Limit, + totalRecordCount: result.TotalRecordCount, + showLimit: false, + updatePageSizeSetting: false, + addLayoutButton: false, + sortButton: false, + filterButton: false + }); + var i; + var length; + var elems = tabContent.querySelectorAll(".paging"); + + for (i = 0, length = elems.length; i < length; i++) { elems[i].innerHTML = pagingHtml; - for (elems = tabContent.querySelectorAll(".btnNextPage"), i = 0, length = elems.length; i < length; i++) + } + + elems = tabContent.querySelectorAll(".btnNextPage"); + for (i = 0, length = elems.length; i < length; i++) { elems[i].addEventListener("click", onNextPageClick); - for (elems = tabContent.querySelectorAll(".btnPreviousPage"), i = 0, length = elems.length; i < length; i++) - elems[i].addEventListener("click", onPreviousPageClick) + } + + elems = tabContent.querySelectorAll(".btnPreviousPage"); + for (i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener("click", onPreviousPageClick); + } + isLoading = false; loading.hide(); } function getItemsHtml(items) { + var html; var viewStyle = self.getCurrentViewStyle(); - return "Thumb" == viewStyle ? cardBuilder.getCardsHtml({ - items: items, - shape: "backdrop", - preferThumb: !0, - context: "movies", - lazy: !0, - overlayPlayButton: !0, - showTitle: !0, - showYear: !0, - centerText: !0 - }) : "ThumbCard" == viewStyle ? cardBuilder.getCardsHtml({ - items: items, - shape: "backdrop", - preferThumb: !0, - context: "movies", - lazy: !0, - cardLayout: !0, - showTitle: !0, - showYear: !0, - centerText: !0 - }) : "Banner" == viewStyle ? cardBuilder.getCardsHtml({ - items: items, - shape: "banner", - preferBanner: !0, - context: "movies", - lazy: !0 - }) : "List" == viewStyle ? listView.getListViewHtml({ - items: items, - context: "movies", - sortBy: query.SortBy - }) : "PosterCard" == viewStyle ? cardBuilder.getCardsHtml({ - items: items, - shape: "portrait", - context: "movies", - showTitle: !0, - showYear: !0, - centerText: !0, - lazy: !0, - cardLayout: !0 - }) : cardBuilder.getCardsHtml({ - items: items, - shape: "portrait", - context: "movies", - overlayPlayButton: !0, - showTitle: !0, - showYear: !0, - centerText: !0 - }) + + if (viewStyle == "Thumb") { + html = cardBuilder.getCardsHtml({ + items: items, + shape: "backdrop", + preferThumb: true, + context: "movies", + lazy: true, + overlayPlayButton: true, + showTitle: true, + showYear: true, + centerText: true + }); + } else if (viewStyle == "ThumbCard") { + html = cardBuilder.getCardsHtml({ + items: items, + shape: "backdrop", + preferThumb: true, + context: "movies", + lazy: true, + cardLayout: true, + showTitle: true, + showYear: true, + centerText: true + }); + } else if (viewStyle == "Banner") { + html = cardBuilder.getCardsHtml({ + items: items, + shape: "banner", + preferBanner: true, + context: "movies", + lazy: true + }); + } else if (viewStyle == "List") { + html = listView.getListViewHtml({ + items: items, + context: "movies", + sortBy: query.SortBy + }); + } else if (viewStyle == "PosterCard") { + html = cardBuilder.getCardsHtml({ + items: items, + shape: "portrait", + context: "movies", + showTitle: true, + showYear: true, + centerText: true, + lazy: true, + cardLayout: true + }); + } else { + html = cardBuilder.getCardsHtml({ + items: items, + shape: "portrait", + context: "movies", + overlayPlayButton: true, + showTitle: true, + showYear: true, + centerText: true + }); + } + + return html; } function initPage(tabContent) { @@ -114,8 +152,9 @@ define(["loading", "layoutManager", "userSettings", "events", "libraryBrowser", itemsContainer.getItemsHtml = getItemsHtml; itemsContainer.afterRefresh = afterRefresh; var alphaPickerElement = tabContent.querySelector(".alphaPicker"); + if (alphaPickerElement) { - alphaPickerElement.addEventListener("alphavaluechanged", function(e) { + alphaPickerElement.addEventListener("alphavaluechanged", function (e) { var newValue = e.detail.value; query.NameStartsWithOrGreater = newValue; query.StartIndex = 0; @@ -125,109 +164,132 @@ define(["loading", "layoutManager", "userSettings", "events", "libraryBrowser", element: alphaPickerElement, valueChangeEvent: "click" }); + if (layoutManager.desktop || layoutManager.mobile) { alphaPickerElement.classList.add("alphabetPicker-right"); itemsContainer.classList.remove("padded-left-withalphapicker"); itemsContainer.classList.add("padded-right-withalphapicker"); } } + var btnFilter = tabContent.querySelector(".btnFilter"); - btnFilter && btnFilter.addEventListener("click", function() { - self.showFilterMenu() - }); + + if (btnFilter) { + btnFilter.addEventListener("click", function () { + self.showFilterMenu(); + }); + } var btnSort = tabContent.querySelector(".btnSort"); - btnSort && btnSort.addEventListener("click", function(e) { - libraryBrowser.showSortMenu({ - items: [{ - name: Globalize.translate("OptionNameSort"), - id: "SortName,ProductionYear" - }, { - name: Globalize.translate("OptionImdbRating"), - id: "CommunityRating,SortName,ProductionYear" - }, { - name: Globalize.translate("OptionCriticRating"), - id: "CriticRating,SortName,ProductionYear" - }, { - name: Globalize.translate("OptionDateAdded"), - id: "DateCreated,SortName,ProductionYear" - }, { - name: Globalize.translate("OptionDatePlayed"), - id: "DatePlayed,SortName,ProductionYear" - }, { - name: Globalize.translate("OptionParentalRating"), - id: "OfficialRating,SortName,ProductionYear" - }, { - name: Globalize.translate("OptionPlayCount"), - id: "PlayCount,SortName,ProductionYear" - }, { - name: Globalize.translate("OptionReleaseDate"), - id: "PremiereDate,SortName,ProductionYear" - }, { - name: Globalize.translate("OptionRuntime"), - id: "Runtime,SortName,ProductionYear" - }], - callback: function() { - query.StartIndex = 0, userSettings.saveQuerySettings(savedQueryKey, query), itemsContainer.refreshItems() - }, - query: query, - button: e.target - }) - }); + + if (btnSort) { + btnSort.addEventListener("click", function (e) { + libraryBrowser.showSortMenu({ + items: [{ + name: Globalize.translate("OptionNameSort"), + id: "SortName,ProductionYear" + }, { + name: Globalize.translate("OptionImdbRating"), + id: "CommunityRating,SortName,ProductionYear" + }, { + name: Globalize.translate("OptionCriticRating"), + id: "CriticRating,SortName,ProductionYear" + }, { + name: Globalize.translate("OptionDateAdded"), + id: "DateCreated,SortName,ProductionYear" + }, { + name: Globalize.translate("OptionDatePlayed"), + id: "DatePlayed,SortName,ProductionYear" + }, { + name: Globalize.translate("OptionParentalRating"), + id: "OfficialRating,SortName,ProductionYear" + }, { + name: Globalize.translate("OptionPlayCount"), + id: "PlayCount,SortName,ProductionYear" + }, { + name: Globalize.translate("OptionReleaseDate"), + id: "PremiereDate,SortName,ProductionYear" + }, { + name: Globalize.translate("OptionRuntime"), + id: "Runtime,SortName,ProductionYear" + }], + callback: function () { + query.StartIndex = 0; + userSettings.saveQuerySettings(savedQueryKey, query); + itemsContainer.refreshItems(); + }, + query: query, + button: e.target + }); + }); + } var btnSelectView = tabContent.querySelector(".btnSelectView"); - btnSelectView.addEventListener("click", function(e) { - libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), "Banner,List,Poster,PosterCard,Thumb,ThumbCard".split(",")) - }), btnSelectView.addEventListener("layoutchange", function(e) { + btnSelectView.addEventListener("click", function (e) { + libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), "Banner,List,Poster,PosterCard,Thumb,ThumbCard".split(",")); + }); + btnSelectView.addEventListener("layoutchange", function (e) { var viewStyle = e.detail.viewStyle; userSettings.set(savedViewKey, viewStyle); query.StartIndex = 0; onViewStyleChange(); itemsContainer.refreshItems(); - }) + }); } - var self = this, - itemsContainer = tabContent.querySelector(".itemsContainer"), - savedQueryKey = params.topParentId + "-" + options.mode, - savedViewKey = savedQueryKey + "-view", - query = { - SortBy: "SortName,ProductionYear", - SortOrder: "Ascending", - IncludeItemTypes: "Movie", - Recursive: !0, - Fields: "PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo", - ImageTypeLimit: 1, - EnableImageTypes: "Primary,Backdrop,Banner,Thumb", - StartIndex: 0, - Limit: 100, - ParentId: params.topParentId - }, - isLoading = false; - if (options.mode === "favorites") query.IsFavorite = true; + + var self = this; + var itemsContainer = tabContent.querySelector(".itemsContainer"); + var savedQueryKey = params.topParentId + "-" + options.mode; + var savedViewKey = savedQueryKey + "-view"; + var query = { + SortBy: "SortName,ProductionYear", + SortOrder: "Ascending", + IncludeItemTypes: "Movie", + Recursive: true, + Fields: "PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo", + ImageTypeLimit: 1, + EnableImageTypes: "Primary,Backdrop,Banner,Thumb", + StartIndex: 0, + Limit: 100, + ParentId: params.topParentId + }; + var isLoading = false; + + if (options.mode === "favorites") { + query.IsFavorite = true; + } + query = userSettings.loadQuerySettings(savedQueryKey, query); - self.showFilterMenu = function() { - require(["components/filterdialog/filterdialog"], function(filterDialogFactory) { + + self.showFilterMenu = function () { + require(["components/filterdialog/filterdialog"], function (filterDialogFactory) { var filterDialog = new filterDialogFactory({ query: query, mode: "movies", serverId: ApiClient.serverId() }); - events.on(filterDialog, "filterchange", function() { - query.StartIndex = 0, itemsContainer.refreshItems() - }), filterDialog.show() - }) + events.on(filterDialog, "filterchange", function () { + query.StartIndex = 0; + itemsContainer.refreshItems(); + }); + filterDialog.show(); + }); }; - self.getCurrentViewStyle = function() { - return userSettings.get(savedViewKey) || "Poster" + + self.getCurrentViewStyle = function () { + return userSettings.get(savedViewKey) || "Poster"; }; - self.initTab = function() { + + self.initTab = function () { initPage(tabContent); onViewStyleChange(); }; - self.renderTab = function() { + + self.renderTab = function () { itemsContainer.refreshItems(); updateFilterControls(); }; - self.destroy = function() { - itemsContainer = null - } - } + + self.destroy = function () { + itemsContainer = null; + }; + }; }); diff --git a/src/controllers/movies/moviesrecommended.js b/src/controllers/movies/moviesrecommended.js index 2bab767735..82c0b6a12d 100644 --- a/src/controllers/movies/moviesrecommended.js +++ b/src/controllers/movies/moviesrecommended.js @@ -1,16 +1,16 @@ -define(["events", "layoutManager", "inputManager", "userSettings", "libraryMenu", "mainTabsManager", "cardBuilder", "dom", "imageLoader", "playbackManager", "emby-itemscontainer", "emby-tabs", "emby-button"], function(events, layoutManager, inputManager, userSettings, libraryMenu, mainTabsManager, cardBuilder, dom, imageLoader, playbackManager) { +define(["events", "layoutManager", "inputManager", "userSettings", "libraryMenu", "mainTabsManager", "cardBuilder", "dom", "imageLoader", "playbackManager", "emby-itemscontainer", "emby-tabs", "emby-button"], function (events, layoutManager, inputManager, userSettings, libraryMenu, mainTabsManager, cardBuilder, dom, imageLoader, playbackManager) { "use strict"; function enableScrollX() { - return !layoutManager.desktop + return !layoutManager.desktop; } function getPortraitShape() { - return enableScrollX() ? "overflowPortrait" : "portrait" + return enableScrollX() ? "overflowPortrait" : "portrait"; } function getThumbShape() { - return enableScrollX() ? "overflowBackdrop" : "backdrop" + return enableScrollX() ? "overflowBackdrop" : "backdrop"; } function loadLatest(page, userId, parentId) { @@ -21,118 +21,168 @@ define(["events", "layoutManager", "inputManager", "userSettings", "libraryMenu" ParentId: parentId, ImageTypeLimit: 1, EnableImageTypes: "Primary,Backdrop,Banner,Thumb", - EnableTotalRecordCount: !1 + EnableTotalRecordCount: false }; - ApiClient.getJSON(ApiClient.getUrl("Users/" + userId + "/Items/Latest", options)).then(function(items) { - var allowBottomPadding = !enableScrollX(), - container = page.querySelector("#recentlyAddedItems"); + ApiClient.getJSON(ApiClient.getUrl("Users/" + userId + "/Items/Latest", options)).then(function (items) { + var allowBottomPadding = !enableScrollX(); + var container = page.querySelector("#recentlyAddedItems"); cardBuilder.buildCards(items, { itemsContainer: container, shape: getPortraitShape(), - scalable: !0, - overlayPlayButton: !0, + scalable: true, + overlayPlayButton: true, allowBottomPadding: allowBottomPadding, - showTitle: !0, - showYear: !0, - centerText: !0 - }) - }) + showTitle: true, + showYear: true, + centerText: true + }); + }); } function loadResume(page, userId, parentId) { - var screenWidth = dom.getWindowSize().innerWidth, - options = { - SortBy: "DatePlayed", - SortOrder: "Descending", - IncludeItemTypes: "Movie", - Filters: "IsResumable", - Limit: screenWidth >= 1920 ? 5 : screenWidth >= 1600 ? 5 : 3, - Recursive: !0, - Fields: "PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo", - CollapseBoxSetItems: !1, - ParentId: parentId, - ImageTypeLimit: 1, - EnableImageTypes: "Primary,Backdrop,Banner,Thumb", - EnableTotalRecordCount: !1 - }; - ApiClient.getItems(userId, options).then(function(result) { - result.Items.length ? page.querySelector("#resumableSection").classList.remove("hide") : page.querySelector("#resumableSection").classList.add("hide"); - var allowBottomPadding = !enableScrollX(), - container = page.querySelector("#resumableItems"); + var screenWidth = dom.getWindowSize().innerWidth; + var options = { + SortBy: "DatePlayed", + SortOrder: "Descending", + IncludeItemTypes: "Movie", + Filters: "IsResumable", + Limit: screenWidth >= 1920 ? 5 : screenWidth >= 1600 ? 5 : 3, + Recursive: true, + Fields: "PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo", + CollapseBoxSetItems: false, + ParentId: parentId, + ImageTypeLimit: 1, + EnableImageTypes: "Primary,Backdrop,Banner,Thumb", + EnableTotalRecordCount: false + }; + ApiClient.getItems(userId, options).then(function (result) { + if (result.Items.length) { + page.querySelector("#resumableSection").classList.remove("hide"); + } else { + page.querySelector("#resumableSection").classList.add("hide"); + } + + var allowBottomPadding = !enableScrollX(); + var container = page.querySelector("#resumableItems"); cardBuilder.buildCards(result.Items, { itemsContainer: container, - preferThumb: !0, + preferThumb: true, shape: getThumbShape(), - scalable: !0, - overlayPlayButton: !0, + scalable: true, + overlayPlayButton: true, allowBottomPadding: allowBottomPadding, - cardLayout: !1, - showTitle: !0, - showYear: !0, - centerText: !0 - }) - }) + cardLayout: false, + showTitle: true, + showYear: true, + centerText: true + }); + }); } function getRecommendationHtml(recommendation) { - var html = "", - title = ""; + var html = ""; + var title = ""; + switch (recommendation.RecommendationType) { case "SimilarToRecentlyPlayed": title = Globalize.translate("RecommendationBecauseYouWatched").replace("{0}", recommendation.BaselineItemName); break; + case "SimilarToLikedItem": title = Globalize.translate("RecommendationBecauseYouLike").replace("{0}", recommendation.BaselineItemName); break; + case "HasDirectorFromRecentlyPlayed": case "HasLikedDirector": title = Globalize.translate("RecommendationDirectedBy").replace("{0}", recommendation.BaselineItemName); break; + case "HasActorFromRecentlyPlayed": case "HasLikedActor": - title = Globalize.translate("RecommendationStarring").replace("{0}", recommendation.BaselineItemName) + title = Globalize.translate("RecommendationStarring").replace("{0}", recommendation.BaselineItemName); + break; } - html += '
', html += '

' + title + "

"; - var allowBottomPadding = !0; - return enableScrollX() ? (allowBottomPadding = !1, html += '
') : html += '
', html += cardBuilder.getCardsHtml(recommendation.Items, { + + html += '
'; + html += '

' + title + "

"; + var allowBottomPadding = true; + + if (enableScrollX()) { + allowBottomPadding = false; + html += '
'; + } else { + html += '
'; + } + + html += cardBuilder.getCardsHtml(recommendation.Items, { shape: getPortraitShape(), - scalable: !0, - overlayPlayButton: !0, + scalable: true, + overlayPlayButton: true, allowBottomPadding: allowBottomPadding - }), html += "
", html += "
" + }); + html += "
"; + html += "
"; + return html; } function loadSuggestions(page, userId, parentId) { - var screenWidth = dom.getWindowSize().innerWidth, - url = ApiClient.getUrl("Movies/Recommendations", { - userId: userId, - categoryLimit: 6, - ItemLimit: screenWidth >= 1920 ? 8 : screenWidth >= 1600 ? 8 : screenWidth >= 1200 ? 6 : 5, - Fields: "PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo", - ImageTypeLimit: 1, - EnableImageTypes: "Primary,Backdrop,Banner,Thumb" - }); - ApiClient.getJSON(url).then(function(recommendations) { - if (!recommendations.length) return page.querySelector(".noItemsMessage").classList.remove("hide"), void(page.querySelector(".recommendations").innerHTML = ""); + var screenWidth = dom.getWindowSize().innerWidth; + var url = ApiClient.getUrl("Movies/Recommendations", { + userId: userId, + categoryLimit: 6, + ItemLimit: screenWidth >= 1920 ? 8 : screenWidth >= 1600 ? 8 : screenWidth >= 1200 ? 6 : 5, + Fields: "PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo", + ImageTypeLimit: 1, + EnableImageTypes: "Primary,Backdrop,Banner,Thumb" + }); + ApiClient.getJSON(url).then(function (recommendations) { + if (!recommendations.length) { + page.querySelector(".noItemsMessage").classList.remove("hide"); + page.querySelector(".recommendations").innerHTML = ""; + return; + } + var html = recommendations.map(getRecommendationHtml).join(""); page.querySelector(".noItemsMessage").classList.add("hide"); var recs = page.querySelector(".recommendations"); - recs.innerHTML = html, imageLoader.lazyChildren(recs) - }) + recs.innerHTML = html; + imageLoader.lazyChildren(recs); + }); } function setScrollClasses(elem, scrollX) { - scrollX ? (elem.classList.add("hiddenScrollX"), layoutManager.tv && elem.classList.add("smoothScrollX"), elem.classList.add("scrollX"), elem.classList.remove("vertical-wrap")) : (elem.classList.remove("hiddenScrollX"), elem.classList.remove("smoothScrollX"), elem.classList.remove("scrollX"), elem.classList.add("vertical-wrap")) + if (scrollX) { + elem.classList.add("hiddenScrollX"); + + if (layoutManager.tv) { + elem.classList.add("smoothScrollX"); + } + + elem.classList.add("scrollX"); + elem.classList.remove("vertical-wrap"); + } else { + elem.classList.remove("hiddenScrollX"); + elem.classList.remove("smoothScrollX"); + elem.classList.remove("scrollX"); + elem.classList.add("vertical-wrap"); + } } function initSuggestedTab(page, tabContent) { - for (var containers = tabContent.querySelectorAll(".itemsContainer"), i = 0, length = containers.length; i < length; i++) setScrollClasses(containers[i], enableScrollX()) + var containers = tabContent.querySelectorAll(".itemsContainer"); + + for (var i = 0, length = containers.length; i < length; i++) { + setScrollClasses(containers[i], enableScrollX()); + } } function loadSuggestionsTab(view, params, tabContent) { - var parentId = params.topParentId, - userId = ApiClient.getCurrentUserId(); - console.log("loadSuggestionsTab"), loadResume(tabContent, userId, parentId), loadLatest(tabContent, userId, parentId), loadSuggestions(tabContent, userId, parentId) + var parentId = params.topParentId; + var userId = ApiClient.getCurrentUserId(); + console.log("loadSuggestionsTab"); + loadResume(tabContent, userId, parentId); + loadLatest(tabContent, userId, parentId); + loadSuggestions(tabContent, userId, parentId); } function getTabs() { @@ -151,126 +201,196 @@ define(["events", "layoutManager", "inputManager", "userSettings", "libraryMenu" }, { name: Globalize.translate("ButtonSearch"), cssClass: "searchTabButton" - }] + }]; } function getDefaultTabIndex(folderId) { switch (userSettings.get("landing-" + folderId)) { case "suggestions": return 1; + case "favorites": return 3; + case "collections": return 4; + case "genres": return 5; + default: - return 0 + return 0; } } - return function(view, params) { + + return function (view, params) { function onBeforeTabChange(e) { - preLoadTab(view, parseInt(e.detail.selectedTabIndex)) + preLoadTab(view, parseInt(e.detail.selectedTabIndex)); } function onTabChange(e) { var newIndex = parseInt(e.detail.selectedTabIndex); - loadTab(view, newIndex) + loadTab(view, newIndex); } function getTabContainers() { - return view.querySelectorAll(".pageTabContent") + return view.querySelectorAll(".pageTabContent"); } function initTabs() { - mainTabsManager.setTabs(view, currentTabIndex, getTabs, getTabContainers, onBeforeTabChange, onTabChange) + mainTabsManager.setTabs(view, currentTabIndex, getTabs, getTabContainers, onBeforeTabChange, onTabChange); } function getTabController(page, index, callback) { var depends = []; + switch (index) { case 0: depends.push("controllers/movies/movies"); break; + case 1: break; + case 2: depends.push("controllers/movies/movietrailers"); break; + case 3: depends.push("controllers/movies/movies"); break; + case 4: depends.push("controllers/movies/moviecollections"); break; + case 5: depends.push("controllers/movies/moviegenres"); break; + case 6: - depends.push("scripts/searchtab") + depends.push("scripts/searchtab"); } - require(depends, function(controllerFactory) { + + require(depends, function (controllerFactory) { var tabContent; - index === suggestionsTabIndex && (tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"), self.tabContent = tabContent); + + if (index === suggestionsTabIndex) { + tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"); + self.tabContent = tabContent; + } + var controller = tabControllers[index]; - controller || (tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"), controller = index === suggestionsTabIndex ? self : 6 === index ? new controllerFactory(view, tabContent, { - collectionType: "movies", - parentId: params.topParentId - }) : 0 === index || 3 === index ? new controllerFactory(view, params, tabContent, { - mode: index ? "favorites" : "movies" - }) : new controllerFactory(view, params, tabContent), tabControllers[index] = controller, controller.initTab && controller.initTab()), callback(controller) - }) + + if (!controller) { + tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"); + + if (index === suggestionsTabIndex) { + controller = self; + } else if (index === 6) { + controller = new controllerFactory(view, tabContent, { + collectionType: "movies", + parentId: params.topParentId + }); + } else if (index == 0 || index == 3) { + controller = new controllerFactory(view, params, tabContent, { + mode: index ? "favorites" : "movies" + }); + } else { + controller = new controllerFactory(view, params, tabContent); + } + + tabControllers[index] = controller; + + if (controller.initTab) { + controller.initTab(); + } + } + + callback(controller); + }); } function preLoadTab(page, index) { - getTabController(page, index, function(controller) { - -1 == renderedTabs.indexOf(index) && controller.preRender && controller.preRender() - }) + getTabController(page, index, function (controller) { + if (renderedTabs.indexOf(index) == -1 && controller.preRender) { + controller.preRender(); + } + }); } function loadTab(page, index) { - currentTabIndex = index, getTabController(page, index, function(controller) { - initialTabIndex = null, -1 == renderedTabs.indexOf(index) && (renderedTabs.push(index), controller.renderTab()) - }) + currentTabIndex = index; + getTabController(page, index, function (controller) { + initialTabIndex = null; + + if (renderedTabs.indexOf(index) == -1) { + renderedTabs.push(index); + controller.renderTab(); + } + }); } function onPlaybackStop(e, state) { - state.NowPlayingItem && "Video" == state.NowPlayingItem.MediaType && (renderedTabs = [], mainTabsManager.getTabsElement().triggerTabChange()) + if (state.NowPlayingItem && state.NowPlayingItem.MediaType == "Video") { + renderedTabs = []; + mainTabsManager.getTabsElement().triggerTabChange(); + } } function onInputCommand(e) { switch (e.detail.command) { case "search": - e.preventDefault(), Dashboard.navigate("search.html?collectionType=movies&parentId=" + params.topParentId) + e.preventDefault(); + Dashboard.navigate("search.html?collectionType=movies&parentId=" + params.topParentId); } } - var isViewRestored, self = this, - currentTabIndex = parseInt(params.tab || getDefaultTabIndex(params.topParentId)), - initialTabIndex = currentTabIndex, - suggestionsTabIndex = 1; - self.initTab = function() { + + var isViewRestored; + var self = this; + var currentTabIndex = parseInt(params.tab || getDefaultTabIndex(params.topParentId)); + var initialTabIndex = currentTabIndex; + var suggestionsTabIndex = 1; + + self.initTab = function () { var tabContent = view.querySelector(".pageTabContent[data-index='" + suggestionsTabIndex + "']"); initSuggestedTab(view, tabContent); - }, self.renderTab = function() { - var tabContent = view.querySelector(".pageTabContent[data-index='" + suggestionsTabIndex + "']"); - loadSuggestionsTab(view, params, tabContent) }; - var tabControllers = [], - renderedTabs = []; - view.addEventListener("viewshow", function(e) { + + self.renderTab = function () { + var tabContent = view.querySelector(".pageTabContent[data-index='" + suggestionsTabIndex + "']"); + loadSuggestionsTab(view, params, tabContent); + }; + + var tabControllers = []; + var renderedTabs = []; + view.addEventListener("viewshow", function (e) { if (isViewRestored = e.detail.isRestored, initTabs(), !view.getAttribute("data-title")) { var parentId = params.topParentId; - parentId ? ApiClient.getItem(ApiClient.getCurrentUserId(), parentId).then(function(item) { - view.setAttribute("data-title", item.Name), libraryMenu.setTitle(item.Name) - }) : (view.setAttribute("data-title", Globalize.translate("TabMovies")), libraryMenu.setTitle(Globalize.translate("TabMovies"))) + + if (parentId) { + ApiClient.getItem(ApiClient.getCurrentUserId(), parentId).then(function (item) { + view.setAttribute("data-title", item.Name); + libraryMenu.setTitle(item.Name); + }); + } else { + view.setAttribute("data-title", Globalize.translate("TabMovies")); + libraryMenu.setTitle(Globalize.translate("TabMovies")); + } } - events.on(playbackManager, "playbackstop", onPlaybackStop), inputManager.on(window, onInputCommand) - }), view.addEventListener("viewbeforehide", function(e) { - inputManager.off(window, onInputCommand) - }), view.addEventListener("viewdestroy", function(e) { - tabControllers.forEach(function(t) { - t.destroy && t.destroy() - }) - }) - } -}); \ No newline at end of file + + events.on(playbackManager, "playbackstop", onPlaybackStop); + inputManager.on(window, onInputCommand); + }); + view.addEventListener("viewbeforehide", function (e) { + inputManager.off(window, onInputCommand); + }); + view.addEventListener("viewdestroy", function (e) { + tabControllers.forEach(function (t) { + if (t.destroy) { + t.destroy(); + } + }); + }); + }; +}); diff --git a/src/controllers/movies/movietrailers.js b/src/controllers/movies/movietrailers.js index 2d1fdda63c..3e62298613 100644 --- a/src/controllers/movies/movietrailers.js +++ b/src/controllers/movies/movietrailers.js @@ -1,185 +1,261 @@ -define(["layoutManager", "loading", "events", "libraryBrowser", "imageLoader", "alphaPicker", "listView", "cardBuilder", "apphost", "emby-itemscontainer"], function(layoutManager, loading, events, libraryBrowser, imageLoader, alphaPicker, listView, cardBuilder, appHost) { +define(["layoutManager", "loading", "events", "libraryBrowser", "imageLoader", "alphaPicker", "listView", "cardBuilder", "apphost", "emby-itemscontainer"], function (layoutManager, loading, events, libraryBrowser, imageLoader, alphaPicker, listView, cardBuilder, appHost) { "use strict"; - return function(view, params, tabContent) { + + return function (view, params, tabContent) { function getPageData(context) { - var key = getSavedQueryKey(context), - pageData = data[key]; - return pageData || (pageData = data[key] = { - query: { - SortBy: "SortName", - SortOrder: "Ascending", - IncludeItemTypes: "Trailer", - Recursive: !0, - Fields: "PrimaryImageAspectRatio,SortName,BasicSyncInfo", - ImageTypeLimit: 1, - EnableImageTypes: "Primary,Backdrop,Banner,Thumb", - StartIndex: 0, - Limit: pageSize - }, - view: libraryBrowser.getSavedView(key) || "Poster" - }, libraryBrowser.loadSavedQueryValues(key, pageData.query)), pageData + var key = getSavedQueryKey(context); + var pageData = data[key]; + + if (!pageData) { + pageData = data[key] = { + query: { + SortBy: "SortName", + SortOrder: "Ascending", + IncludeItemTypes: "Trailer", + Recursive: true, + Fields: "PrimaryImageAspectRatio,SortName,BasicSyncInfo", + ImageTypeLimit: 1, + EnableImageTypes: "Primary,Backdrop,Banner,Thumb", + StartIndex: 0, + Limit: pageSize + }, + view: libraryBrowser.getSavedView(key) || "Poster" + }; + libraryBrowser.loadSavedQueryValues(key, pageData.query); + } + + return pageData; } function getQuery(context) { - return getPageData(context).query + return getPageData(context).query; } function getSavedQueryKey(context) { - return context.savedQueryKey || (context.savedQueryKey = libraryBrowser.getSavedQueryKey("trailers")), context.savedQueryKey + if (!context.savedQueryKey) { + context.savedQueryKey = libraryBrowser.getSavedQueryKey("trailers"); + } + + return context.savedQueryKey; } function reloadItems() { loading.show(); isLoading = true; var query = getQuery(tabContent); - ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function(result) { + ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function (result) { function onNextPageClick() { - if (isLoading) return; - query.StartIndex += query.Limit, reloadItems() + if (isLoading) { + return; + } + + query.StartIndex += query.Limit; + reloadItems(); } function onPreviousPageClick() { - if (isLoading) return; - query.StartIndex -= query.Limit, reloadItems() + if (isLoading) { + return; + } + + query.StartIndex -= query.Limit; + reloadItems(); } - window.scrollTo(0, 0), updateFilterControls(tabContent); - var html, pagingHtml = libraryBrowser.getQueryPagingHtml({ - startIndex: query.StartIndex, - limit: query.Limit, - totalRecordCount: result.TotalRecordCount, - showLimit: !1, - updatePageSizeSetting: !1, - addLayoutButton: !1, - sortButton: !1, - filterButton: !1 - }), - viewStyle = self.getCurrentViewStyle(); - html = "Thumb" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "backdrop", - preferThumb: !0, - context: "movies", - overlayPlayButton: !0 - }) : "ThumbCard" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "backdrop", - preferThumb: !0, - context: "movies", - cardLayout: !0, - showTitle: !0, - showYear: !0, - centerText: !0 - }) : "Banner" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "banner", - preferBanner: !0, - context: "movies" - }) : "List" == viewStyle ? listView.getListViewHtml({ - items: result.Items, - context: "movies", - sortBy: query.SortBy - }) : "PosterCard" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "portrait", - context: "movies", - showTitle: !0, - showYear: !0, - centerText: !0, - cardLayout: !0 - }) : cardBuilder.getCardsHtml({ - items: result.Items, - shape: "portrait", - context: "movies", - centerText: !0, - overlayPlayButton: !0, - showTitle: !0, - showYear: !0 + + window.scrollTo(0, 0); + updateFilterControls(tabContent); + var pagingHtml = libraryBrowser.getQueryPagingHtml({ + startIndex: query.StartIndex, + limit: query.Limit, + totalRecordCount: result.TotalRecordCount, + showLimit: false, + updatePageSizeSetting: false, + addLayoutButton: false, + sortButton: false, + filterButton: false }); - var i, length, elems = tabContent.querySelectorAll(".paging"); - for (i = 0, length = elems.length; i < length; i++) elems[i].innerHTML = pagingHtml; - for (elems = tabContent.querySelectorAll(".btnNextPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onNextPageClick); - for (elems = tabContent.querySelectorAll(".btnPreviousPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onPreviousPageClick); - result.Items.length || (html = '

' + Globalize.translate("MessageNoTrailersFound") + "

"); + var html; + var viewStyle = self.getCurrentViewStyle(); + + if (viewStyle == "Thumb") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "backdrop", + preferThumb: true, + context: "movies", + overlayPlayButton: true + }); + } else if (viewStyle == "ThumbCard") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "backdrop", + preferThumb: true, + context: "movies", + cardLayout: true, + showTitle: true, + showYear: true, + centerText: true + }); + } else if (viewStyle == "Banner") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "banner", + preferBanner: true, + context: "movies" + }); + } else if (viewStyle == "List") { + html = listView.getListViewHtml({ + items: result.Items, + context: "movies", + sortBy: query.SortBy + }); + } else if (viewStyle == "PosterCard") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "portrait", + context: "movies", + showTitle: true, + showYear: true, + cardLayout: true, + centerText: true + }); + } else { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "portrait", + context: "movies", + centerText: true, + overlayPlayButton: true, + showTitle: true, + showYear: true + }); + } + + var i; + var length; + var elems = tabContent.querySelectorAll(".paging"); + + for (i = 0, length = elems.length; i < length; i++) { + elems[i].innerHTML = pagingHtml; + } + + elems = tabContent.querySelectorAll(".btnNextPage"); + for (i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener("click", onNextPageClick); + } + + elems = tabContent.querySelectorAll(".btnPreviousPage"); + for (i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener("click", onPreviousPageClick); + } + + if (!result.Items.length) { + html = '

' + Globalize.translate("MessageNoTrailersFound") + "

"; + } + var itemsContainer = tabContent.querySelector(".itemsContainer"); itemsContainer.innerHTML = html; imageLoader.lazyChildren(itemsContainer); libraryBrowser.saveQueryValues(getSavedQueryKey(tabContent), query); loading.hide(); isLoading = false; - }) + }); } function updateFilterControls(tabContent) { var query = getQuery(tabContent); - self.alphaPicker.value(query.NameStartsWithOrGreater) + self.alphaPicker.value(query.NameStartsWithOrGreater); } - var self = this, - pageSize = 100, - data = {}, - isLoading = false; - self.showFilterMenu = function() { - require(["components/filterdialog/filterdialog"], function(filterDialogFactory) { - var filterDialog = new filterDialogFactory({ - query: getQuery(tabContent), - mode: "movies", - serverId: ApiClient.serverId() - }); - events.on(filterDialog, "filterchange", function() { - getQuery(tabContent).StartIndex = 0, reloadItems() - }), filterDialog.show() - }) - }, self.getCurrentViewStyle = function() { - return getPageData(tabContent).view - }, - function(tabContent) { - var alphaPickerElement = tabContent.querySelector(".alphaPicker"); - if (alphaPickerElement.addEventListener("alphavaluechanged", function(e) { - var newValue = e.detail.value, - query = getQuery(tabContent); - query.NameStartsWithOrGreater = newValue, query.StartIndex = 0, reloadItems() - }), self.alphaPicker = new alphaPicker({ - element: alphaPickerElement, - valueChangeEvent: "click" - }), layoutManager.desktop || layoutManager.mobile) { - tabContent.querySelector(".alphaPicker").classList.add("alphabetPicker-right"); - var itemsContainer = tabContent.querySelector(".itemsContainer"); - itemsContainer.classList.remove("padded-left-withalphapicker"), itemsContainer.classList.add("padded-right-withalphapicker") - } - tabContent.querySelector(".btnFilter").addEventListener("click", function() { - self.showFilterMenu() - }), tabContent.querySelector(".btnSort").addEventListener("click", function(e) { - libraryBrowser.showSortMenu({ - items: [{ - name: Globalize.translate("OptionNameSort"), - id: "SortName" - }, { - name: Globalize.translate("OptionImdbRating"), - id: "CommunityRating,SortName" - }, { - name: Globalize.translate("OptionDateAdded"), - id: "DateCreated,SortName" - }, { - name: Globalize.translate("OptionDatePlayed"), - id: "DatePlayed,SortName" - }, { - name: Globalize.translate("OptionParentalRating"), - id: "OfficialRating,SortName" - }, { - name: Globalize.translate("OptionPlayCount"), - id: "PlayCount,SortName" - }, { - name: Globalize.translate("OptionReleaseDate"), - id: "PremiereDate,SortName" - }], - callback: function() { - getQuery(tabContent).StartIndex = 0, reloadItems() - }, - query: getQuery(tabContent), - button: e.target - }) - }) - }(tabContent), self.renderTab = function() { - reloadItems(), updateFilterControls(tabContent) - }, self.destroy = function() {} - } + + var self = this; + var pageSize = 100; + var data = {}; + var isLoading = false; + + self.showFilterMenu = function () { + require(["components/filterdialog/filterdialog"], function (filterDialogFactory) { + var filterDialog = new filterDialogFactory({ + query: getQuery(tabContent), + mode: "movies", + serverId: ApiClient.serverId() + }); + events.on(filterDialog, "filterchange", function () { + getQuery(tabContent).StartIndex = 0; + reloadItems(); + }); + filterDialog.show(); + }); + }; + + self.getCurrentViewStyle = function () { + return getPageData(tabContent).view; + }; + + function initPage(tabContent) { + var alphaPickerElement = tabContent.querySelector(".alphaPicker"); + alphaPickerElement.addEventListener("alphavaluechanged", function (e) { + var newValue = e.detail.value; + var query = getQuery(tabContent); + query.NameStartsWithOrGreater = newValue; + query.StartIndex = 0; + reloadItems(); + }); + self.alphaPicker = new alphaPicker({ + element: alphaPickerElement, + valueChangeEvent: "click" + }); + + if (layoutManager.desktop || layoutManager.mobile) { + tabContent.querySelector(".alphaPicker").classList.add("alphabetPicker-right"); + var itemsContainer = tabContent.querySelector(".itemsContainer"); + itemsContainer.classList.remove("padded-left-withalphapicker"); + itemsContainer.classList.add("padded-right-withalphapicker"); + } + + tabContent.querySelector(".btnFilter").addEventListener("click", function () { + self.showFilterMenu(); + }); + tabContent.querySelector(".btnSort").addEventListener("click", function (e) { + libraryBrowser.showSortMenu({ + items: [{ + name: Globalize.translate("OptionNameSort"), + id: "SortName" + }, { + name: Globalize.translate("OptionImdbRating"), + id: "CommunityRating,SortName" + }, { + name: Globalize.translate("OptionDateAdded"), + id: "DateCreated,SortName" + }, { + name: Globalize.translate("OptionDatePlayed"), + id: "DatePlayed,SortName" + }, { + name: Globalize.translate("OptionParentalRating"), + id: "OfficialRating,SortName" + }, { + name: Globalize.translate("OptionPlayCount"), + id: "PlayCount,SortName" + }, { + name: Globalize.translate("OptionReleaseDate"), + id: "PremiereDate,SortName" + }], + callback: function () { + getQuery(tabContent).StartIndex = 0; + reloadItems(); + }, + query: getQuery(tabContent), + button: e.target + }); + }); + } + + initPage(tabContent); + + self.renderTab = function () { + reloadItems(); + updateFilterControls(tabContent); + }; + + self.destroy = function () {}; + }; }); diff --git a/src/controllers/music/musicalbums.js b/src/controllers/music/musicalbums.js index 8a562c532d..ac45d9a15b 100644 --- a/src/controllers/music/musicalbums.js +++ b/src/controllers/music/musicalbums.js @@ -1,190 +1,275 @@ -define(["layoutManager", "playbackManager", "loading", "events", "libraryBrowser", "imageLoader", "alphaPicker", "listView", "cardBuilder", "apphost", "emby-itemscontainer"], function(layoutManager, playbackManager, loading, events, libraryBrowser, imageLoader, alphaPicker, listView, cardBuilder, appHost) { +define(["layoutManager", "playbackManager", "loading", "events", "libraryBrowser", "imageLoader", "alphaPicker", "listView", "cardBuilder", "apphost", "emby-itemscontainer"], function (layoutManager, playbackManager, loading, events, libraryBrowser, imageLoader, alphaPicker, listView, cardBuilder, appHost) { "use strict"; - return function(view, params, tabContent) { + + return function (view, params, tabContent) { function playAll() { - ApiClient.getItem(ApiClient.getCurrentUserId(), params.topParentId).then(function(item) { + ApiClient.getItem(ApiClient.getCurrentUserId(), params.topParentId).then(function (item) { playbackManager.play({ items: [item] - }) - }) + }); + }); } function shuffle() { - ApiClient.getItem(ApiClient.getCurrentUserId(), params.topParentId).then(function(item) { + ApiClient.getItem(ApiClient.getCurrentUserId(), params.topParentId).then(function (item) { getQuery(); - playbackManager.shuffle(item, null) - }) + playbackManager.shuffle(item, null); + }); } function getPageData() { var key = getSavedQueryKey(); - return pageData || (pageData = { - query: { - SortBy: "SortName", - SortOrder: "Ascending", - IncludeItemTypes: "MusicAlbum", - Recursive: !0, - Fields: "PrimaryImageAspectRatio,SortName,BasicSyncInfo", - ImageTypeLimit: 1, - EnableImageTypes: "Primary,Backdrop,Banner,Thumb", - StartIndex: 0, - Limit: pageSize - }, - view: libraryBrowser.getSavedView(key) || "Poster" - }, pageData.query.ParentId = params.topParentId, libraryBrowser.loadSavedQueryValues(key, pageData.query)), pageData + + if (!pageData) { + pageData = { + query: { + SortBy: "SortName", + SortOrder: "Ascending", + IncludeItemTypes: "MusicAlbum", + Recursive: true, + Fields: "PrimaryImageAspectRatio,SortName,BasicSyncInfo", + ImageTypeLimit: 1, + EnableImageTypes: "Primary,Backdrop,Banner,Thumb", + StartIndex: 0, + Limit: pageSize + }, + view: libraryBrowser.getSavedView(key) || "Poster" + }; + pageData.query.ParentId = params.topParentId; + libraryBrowser.loadSavedQueryValues(key, pageData.query); + } + + return pageData; } function getQuery() { - return getPageData().query + return getPageData().query; } function getSavedQueryKey() { - return savedQueryKey || (savedQueryKey = libraryBrowser.getSavedQueryKey("musicalbums")), savedQueryKey + if (!savedQueryKey) { + savedQueryKey = libraryBrowser.getSavedQueryKey("musicalbums"); + } + + return savedQueryKey; } function onViewStyleChange() { - var viewStyle = self.getCurrentViewStyle(), - itemsContainer = tabContent.querySelector(".itemsContainer"); - "List" == viewStyle ? (itemsContainer.classList.add("vertical-list"), itemsContainer.classList.remove("vertical-wrap")) : (itemsContainer.classList.remove("vertical-list"), itemsContainer.classList.add("vertical-wrap")), itemsContainer.innerHTML = "" + var viewStyle = self.getCurrentViewStyle(); + var itemsContainer = tabContent.querySelector(".itemsContainer"); + + 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.innerHTML = ""; } function reloadItems(page) { loading.show(); isLoading = true; var query = getQuery(); - ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function(result) { + ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function (result) { function onNextPageClick() { - if (isLoading) return; - query.StartIndex += query.Limit, reloadItems(tabContent) + if (isLoading) { + return; + } + + query.StartIndex += query.Limit; + reloadItems(tabContent); } function onPreviousPageClick() { - if (isLoading) return; - query.StartIndex -= query.Limit, reloadItems(tabContent) + if (isLoading) { + return; + } + + query.StartIndex -= query.Limit; + reloadItems(tabContent); } - window.scrollTo(0, 0), updateFilterControls(page); - var html, pagingHtml = libraryBrowser.getQueryPagingHtml({ - startIndex: query.StartIndex, - limit: query.Limit, - totalRecordCount: result.TotalRecordCount, - showLimit: !1, - updatePageSizeSetting: !1, - addLayoutButton: !1, - sortButton: !1, - filterButton: !1 - }), - viewStyle = self.getCurrentViewStyle(); - html = "List" == viewStyle ? listView.getListViewHtml({ - items: result.Items, - context: "music", - sortBy: query.SortBy, - addToListButton: !0 - }) : "PosterCard" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "square", - context: "music", - showTitle: !0, - coverImage: !0, - showParentTitle: !0, - lazy: !0, - cardLayout: !0 - }) : cardBuilder.getCardsHtml({ - items: result.Items, - shape: "square", - context: "music", - showTitle: !0, - showParentTitle: !0, - lazy: !0, - centerText: !0, - overlayPlayButton: !0 + + window.scrollTo(0, 0); + updateFilterControls(page); + var html; + var pagingHtml = libraryBrowser.getQueryPagingHtml({ + startIndex: query.StartIndex, + limit: query.Limit, + totalRecordCount: result.TotalRecordCount, + showLimit: false, + updatePageSizeSetting: false, + addLayoutButton: false, + sortButton: false, + filterButton: false }); - var i, length, elems = tabContent.querySelectorAll(".paging"); - for (i = 0, length = elems.length; i < length; i++) elems[i].innerHTML = pagingHtml; - for (elems = tabContent.querySelectorAll(".btnNextPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onNextPageClick); - for (elems = tabContent.querySelectorAll(".btnPreviousPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onPreviousPageClick); + var viewStyle = self.getCurrentViewStyle(); + if (viewStyle == "List") { + html = listView.getListViewHtml({ + items: result.Items, + context: "music", + sortBy: query.SortBy, + addToListButton: true + }); + } else if (viewStyle == "PosterCard") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "square", + context: "music", + showTitle: true, + coverImage: true, + showParentTitle: true, + lazy: true, + cardLayout: true + }); + } else { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "square", + context: "music", + showTitle: true, + showParentTitle: true, + lazy: true, + centerText: true, + overlayPlayButton: true + }); + } + var i; + var length; + var elems = tabContent.querySelectorAll(".paging"); + + for (i = 0, length = elems.length; i < length; i++) { + elems[i].innerHTML = pagingHtml; + } + + elems = tabContent.querySelectorAll(".btnNextPage"); + for (i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener("click", onNextPageClick); + } + + elems = tabContent.querySelectorAll(".btnPreviousPage"); + for (i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener("click", onPreviousPageClick); + } + var itemsContainer = tabContent.querySelector(".itemsContainer"); itemsContainer.innerHTML = html; imageLoader.lazyChildren(itemsContainer); libraryBrowser.saveQueryValues(getSavedQueryKey(), query); loading.hide(); isLoading = false; - }) + }); } function updateFilterControls(tabContent) { var query = getQuery(); - self.alphaPicker.value(query.NameStartsWithOrGreater) + self.alphaPicker.value(query.NameStartsWithOrGreater); } - var savedQueryKey, pageData, self = this, - pageSize = 100, - isLoading = false; - self.showFilterMenu = function() { - require(["components/filterdialog/filterdialog"], function(filterDialogFactory) { - var filterDialog = new filterDialogFactory({ - query: getQuery(), - mode: "albums", - serverId: ApiClient.serverId() - }); - events.on(filterDialog, "filterchange", function() { - getQuery().StartIndex = 0, reloadItems(tabContent) - }), filterDialog.show() - }) - }, self.getCurrentViewStyle = function() { - return getPageData().view - }, - function(tabContent) { - var alphaPickerElement = tabContent.querySelector(".alphaPicker"); - if (alphaPickerElement.addEventListener("alphavaluechanged", function(e) { - var newValue = e.detail.value, - query = getQuery(); - query.NameStartsWithOrGreater = newValue, query.StartIndex = 0, reloadItems(tabContent) - }), self.alphaPicker = new alphaPicker({ - element: alphaPickerElement, - valueChangeEvent: "click" - }), layoutManager.desktop || layoutManager.mobile) { - tabContent.querySelector(".alphaPicker").classList.add("alphabetPicker-right"); - var itemsContainer = tabContent.querySelector(".itemsContainer"); - itemsContainer.classList.remove("padded-left-withalphapicker"), itemsContainer.classList.add("padded-right-withalphapicker") - } - tabContent.querySelector(".btnFilter").addEventListener("click", function() { - self.showFilterMenu() - }), tabContent.querySelector(".btnSort").addEventListener("click", function(e) { - libraryBrowser.showSortMenu({ - items: [{ - name: Globalize.translate("OptionNameSort"), - id: "SortName" - }, { - name: Globalize.translate("OptionAlbumArtist"), - id: "AlbumArtist,SortName" - }, { - name: Globalize.translate("OptionCommunityRating"), - id: "CommunityRating,SortName" - }, { - name: Globalize.translate("OptionCriticRating"), - id: "CriticRating,SortName" - }, { - name: Globalize.translate("OptionDateAdded"), - id: "DateCreated,SortName" - }, { - name: Globalize.translate("OptionReleaseDate"), - id: "ProductionYear,PremiereDate,SortName" - }], - callback: function() { - getQuery().StartIndex = 0, reloadItems(tabContent) - }, - query: getQuery(), - button: e.target - }) + + var savedQueryKey; + var pageData; + var self = this; + var pageSize = 100; + var isLoading = false; + + self.showFilterMenu = function () { + require(["components/filterdialog/filterdialog"], function (filterDialogFactory) { + var filterDialog = new filterDialogFactory({ + query: getQuery(), + mode: "albums", + serverId: ApiClient.serverId() }); - var btnSelectView = tabContent.querySelector(".btnSelectView"); - btnSelectView.addEventListener("click", function(e) { - libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), "List,Poster,PosterCard".split(",")) - }), btnSelectView.addEventListener("layoutchange", function(e) { - var viewStyle = e.detail.viewStyle; - getPageData().view = viewStyle, libraryBrowser.saveViewSetting(getSavedQueryKey(), viewStyle), getQuery().StartIndex = 0, onViewStyleChange(), reloadItems(tabContent) - }), tabContent.querySelector(".btnPlayAll").addEventListener("click", playAll), tabContent.querySelector(".btnShuffle").addEventListener("click", shuffle) - }(tabContent), onViewStyleChange(), self.renderTab = function() { - reloadItems(tabContent), updateFilterControls(tabContent) - }, self.destroy = function() {} - } + events.on(filterDialog, "filterchange", function () { + getQuery().StartIndex = 0; + reloadItems(tabContent); + }); + filterDialog.show(); + }); + }; + + self.getCurrentViewStyle = function () { + return getPageData().view; + }; + + function initPage(tabContent) { + var alphaPickerElement = tabContent.querySelector(".alphaPicker"); + + alphaPickerElement.addEventListener("alphavaluechanged", function (e) { + var newValue = e.detail.value; + var query = getQuery(); + query.NameStartsWithOrGreater = newValue; + query.StartIndex = 0; + reloadItems(tabContent); + }); + self.alphaPicker = new alphaPicker({ + element: alphaPickerElement, + valueChangeEvent: "click" + }); + if (layoutManager.desktop || layoutManager.mobile) { + tabContent.querySelector(".alphaPicker").classList.add("alphabetPicker-right"); + var itemsContainer = tabContent.querySelector(".itemsContainer"); + itemsContainer.classList.remove("padded-left-withalphapicker"); + itemsContainer.classList.add("padded-right-withalphapicker"); + } + + tabContent.querySelector(".btnFilter").addEventListener("click", function () { + self.showFilterMenu(); + }); + tabContent.querySelector(".btnSort").addEventListener("click", function (e) { + libraryBrowser.showSortMenu({ + items: [{ + name: Globalize.translate("OptionNameSort"), + id: "SortName" + }, { + name: Globalize.translate("OptionAlbumArtist"), + id: "AlbumArtist,SortName" + }, { + name: Globalize.translate("OptionCommunityRating"), + id: "CommunityRating,SortName" + }, { + name: Globalize.translate("OptionCriticRating"), + id: "CriticRating,SortName" + }, { + name: Globalize.translate("OptionDateAdded"), + id: "DateCreated,SortName" + }, { + name: Globalize.translate("OptionReleaseDate"), + id: "ProductionYear,PremiereDate,SortName" + }], + callback: function () { + getQuery().StartIndex = 0; + reloadItems(tabContent); + }, + query: getQuery(), + button: e.target + }); + }); + var btnSelectView = tabContent.querySelector(".btnSelectView"); + btnSelectView.addEventListener("click", function (e) { + libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), "List,Poster,PosterCard".split(",")); + }); + btnSelectView.addEventListener("layoutchange", function (e) { + var viewStyle = e.detail.viewStyle; + getPageData().view = viewStyle; + libraryBrowser.saveViewSetting(getSavedQueryKey(), viewStyle); + getQuery().StartIndex = 0; + onViewStyleChange(); + reloadItems(tabContent); + }); + tabContent.querySelector(".btnPlayAll").addEventListener("click", playAll); + tabContent.querySelector(".btnShuffle").addEventListener("click", shuffle); + } + + initPage(tabContent); + onViewStyleChange(); + + self.renderTab = function () { + reloadItems(tabContent); + updateFilterControls(tabContent); + }; + + self.destroy = function () {}; + }; }); diff --git a/src/controllers/music/musicartists.js b/src/controllers/music/musicartists.js index b28385169d..5159f635f8 100644 --- a/src/controllers/music/musicartists.js +++ b/src/controllers/music/musicartists.js @@ -1,144 +1,226 @@ -define(["layoutManager", "loading", "events", "libraryBrowser", "imageLoader", "alphaPicker", "listView", "cardBuilder", "apphost", "emby-itemscontainer"], function(layoutManager, loading, events, libraryBrowser, imageLoader, alphaPicker, listView, cardBuilder, appHost) { +define(["layoutManager", "loading", "events", "libraryBrowser", "imageLoader", "alphaPicker", "listView", "cardBuilder", "apphost", "emby-itemscontainer"], function (layoutManager, loading, events, libraryBrowser, imageLoader, alphaPicker, listView, cardBuilder, appHost) { "use strict"; - return function(view, params, tabContent) { + + return function (view, params, tabContent) { function getPageData(context) { - var key = getSavedQueryKey(context), - pageData = data[key]; - return pageData || (pageData = data[key] = { - query: { - SortBy: "SortName", - SortOrder: "Ascending", - Recursive: !0, - Fields: "PrimaryImageAspectRatio,SortName,BasicSyncInfo", - StartIndex: 0, - ImageTypeLimit: 1, - EnableImageTypes: "Primary,Backdrop,Banner,Thumb", - Limit: 100 - }, - view: libraryBrowser.getSavedView(key) || "Poster" - }, pageData.query.ParentId = params.topParentId, libraryBrowser.loadSavedQueryValues(key, pageData.query)), pageData + var key = getSavedQueryKey(context); + var pageData = data[key]; + + if (!pageData) { + pageData = data[key] = { + query: { + SortBy: "SortName", + SortOrder: "Ascending", + Recursive: true, + Fields: "PrimaryImageAspectRatio,SortName,BasicSyncInfo", + StartIndex: 0, + ImageTypeLimit: 1, + EnableImageTypes: "Primary,Backdrop,Banner,Thumb", + Limit: 100 + }, + view: libraryBrowser.getSavedView(key) || "Poster" + }; + pageData.query.ParentId = params.topParentId; + libraryBrowser.loadSavedQueryValues(key, pageData.query); + } + + return pageData; } function getQuery(context) { - return getPageData(context).query + return getPageData(context).query; } function getSavedQueryKey(context) { - return context.savedQueryKey || (context.savedQueryKey = libraryBrowser.getSavedQueryKey(self.mode)), context.savedQueryKey + if (!context.savedQueryKey) { + context.savedQueryKey = libraryBrowser.getSavedQueryKey(self.mode); + } + + return context.savedQueryKey; } function onViewStyleChange() { - var viewStyle = self.getCurrentViewStyle(), - itemsContainer = tabContent.querySelector(".itemsContainer"); - "List" == viewStyle ? (itemsContainer.classList.add("vertical-list"), itemsContainer.classList.remove("vertical-wrap")) : (itemsContainer.classList.remove("vertical-list"), itemsContainer.classList.add("vertical-wrap")), itemsContainer.innerHTML = "" + var viewStyle = self.getCurrentViewStyle(); + var itemsContainer = tabContent.querySelector(".itemsContainer"); + + 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.innerHTML = ""; } function reloadItems(page) { loading.show(); isLoading = true; var query = getQuery(page); - ("albumartists" == self.mode ? ApiClient.getAlbumArtists(ApiClient.getCurrentUserId(), query) : ApiClient.getArtists(ApiClient.getCurrentUserId(), query)).then(function(result) { + var promise = self.mode == 'albumartists' ? + ApiClient.getAlbumArtists(ApiClient.getCurrentUserId(), query) : + ApiClient.getArtists(ApiClient.getCurrentUserId(), query); + promise.then(function (result) { function onNextPageClick() { - if (isLoading) return; - query.StartIndex += query.Limit, reloadItems(tabContent) + if (isLoading) { + return; + } + + query.StartIndex += query.Limit; + reloadItems(tabContent); } function onPreviousPageClick() { - if (isLoading) return; - query.StartIndex -= query.Limit, reloadItems(tabContent) + if (isLoading) { + return; + } + + query.StartIndex -= query.Limit; + reloadItems(tabContent); } - window.scrollTo(0, 0), updateFilterControls(page); - var html, pagingHtml = libraryBrowser.getQueryPagingHtml({ - startIndex: query.StartIndex, - limit: query.Limit, - totalRecordCount: result.TotalRecordCount, - showLimit: !1, - updatePageSizeSetting: !1, - addLayoutButton: !1, - sortButton: !1, - filterButton: !1 - }), - viewStyle = self.getCurrentViewStyle(); - html = "List" == viewStyle ? listView.getListViewHtml({ - items: result.Items, - sortBy: query.SortBy - }) : "PosterCard" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "square", - context: "music", - showTitle: !0, - coverImage: !0, - cardLayout: !0 - }) : cardBuilder.getCardsHtml({ - items: result.Items, - shape: "square", - context: "music", - showTitle: !0, - coverImage: !0, - lazy: !0, - centerText: !0, - overlayPlayButton: !0 + + window.scrollTo(0, 0); + updateFilterControls(page); + var html; + var pagingHtml = libraryBrowser.getQueryPagingHtml({ + startIndex: query.StartIndex, + limit: query.Limit, + totalRecordCount: result.TotalRecordCount, + showLimit: false, + updatePageSizeSetting: false, + addLayoutButton: false, + sortButton: false, + filterButton: false }); - var i, length, elems = tabContent.querySelectorAll(".paging"); - for (i = 0, length = elems.length; i < length; i++) elems[i].innerHTML = pagingHtml; - for (elems = tabContent.querySelectorAll(".btnNextPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onNextPageClick); - for (elems = tabContent.querySelectorAll(".btnPreviousPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onPreviousPageClick); + var viewStyle = self.getCurrentViewStyle(); + if (viewStyle == "List") { + html = listView.getListViewHtml({ + items: result.Items, + sortBy: query.SortBy + }); + } else if (viewStyle == "PosterCard") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "square", + context: "music", + showTitle: true, + coverImage: true, + cardLayout: true + }); + } else { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "square", + context: "music", + showTitle: true, + coverImage: true, + lazy: true, + centerText: true, + overlayPlayButton: true + }); + } + var i; + var length; + var elems = tabContent.querySelectorAll(".paging"); + + for (i = 0, length = elems.length; i < length; i++) { + elems[i].innerHTML = pagingHtml; + } + + elems = tabContent.querySelectorAll(".btnNextPage"); + for (i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener("click", onNextPageClick); + } + + elems = tabContent.querySelectorAll(".btnPreviousPage"); + for (i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener("click", onPreviousPageClick); + } + var itemsContainer = tabContent.querySelector(".itemsContainer"); itemsContainer.innerHTML = html; imageLoader.lazyChildren(itemsContainer); libraryBrowser.saveQueryValues(getSavedQueryKey(page), query); loading.hide(); isLoading = false; - }) + }); } function updateFilterControls(tabContent) { var query = getQuery(tabContent); - self.alphaPicker.value(query.NameStartsWithOrGreater) + self.alphaPicker.value(query.NameStartsWithOrGreater); } - var self = this, - data = {}, - isLoading = false; - self.showFilterMenu = function() { - require(["components/filterdialog/filterdialog"], function(filterDialogFactory) { - var filterDialog = new filterDialogFactory({ - query: getQuery(tabContent), - mode: self.mode, - serverId: ApiClient.serverId() - }); - events.on(filterDialog, "filterchange", function() { - getQuery(tabContent).StartIndex = 0, reloadItems(tabContent) - }), filterDialog.show() - }) - }, self.getCurrentViewStyle = function() { - return getPageData(tabContent).view - }, - function(tabContent) { - var alphaPickerElement = tabContent.querySelector(".alphaPicker"); - if (alphaPickerElement.addEventListener("alphavaluechanged", function(e) { - var newValue = e.detail.value, - query = getQuery(tabContent); - query.NameStartsWithOrGreater = newValue, query.StartIndex = 0, reloadItems(tabContent) - }), self.alphaPicker = new alphaPicker({ - element: alphaPickerElement, - valueChangeEvent: "click" - }), layoutManager.desktop || layoutManager.mobile) { - tabContent.querySelector(".alphaPicker").classList.add("alphabetPicker-right"); - var itemsContainer = tabContent.querySelector(".itemsContainer"); - itemsContainer.classList.remove("padded-left-withalphapicker"), itemsContainer.classList.add("padded-right-withalphapicker") - } - tabContent.querySelector(".btnFilter").addEventListener("click", function() { - self.showFilterMenu() + + var self = this; + var data = {}; + var isLoading = false; + + self.showFilterMenu = function () { + require(["components/filterdialog/filterdialog"], function (filterDialogFactory) { + var filterDialog = new filterDialogFactory({ + query: getQuery(tabContent), + mode: self.mode, + serverId: ApiClient.serverId() }); - var btnSelectView = tabContent.querySelector(".btnSelectView"); - btnSelectView.addEventListener("click", function(e) { - libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), "List,Poster,PosterCard".split(",")) - }), btnSelectView.addEventListener("layoutchange", function(e) { - var viewStyle = e.detail.viewStyle; - getPageData(tabContent).view = viewStyle, libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle), getQuery(tabContent).StartIndex = 0, onViewStyleChange(), reloadItems(tabContent) - }) - }(tabContent), onViewStyleChange(), self.renderTab = function() { - reloadItems(tabContent), updateFilterControls(tabContent) - }, self.destroy = function() {} - } + events.on(filterDialog, "filterchange", function () { + getQuery(tabContent).StartIndex = 0; + reloadItems(tabContent); + }); + filterDialog.show(); + }); + }; + + self.getCurrentViewStyle = function () { + return getPageData(tabContent).view; + }; + + function initPage(tabContent) { + var alphaPickerElement = tabContent.querySelector(".alphaPicker"); + + alphaPickerElement.addEventListener("alphavaluechanged", function (e) { + var newValue = e.detail.value; + var query = getQuery(tabContent); + query.NameStartsWithOrGreater = newValue; + query.StartIndex = 0; + reloadItems(tabContent); + }); + self.alphaPicker = new alphaPicker({ + element: alphaPickerElement, + valueChangeEvent: "click" + }); + if (layoutManager.desktop || layoutManager.mobile) { + tabContent.querySelector(".alphaPicker").classList.add("alphabetPicker-right"); + var itemsContainer = tabContent.querySelector(".itemsContainer"); + itemsContainer.classList.remove("padded-left-withalphapicker"); + itemsContainer.classList.add("padded-right-withalphapicker"); + } + + tabContent.querySelector(".btnFilter").addEventListener("click", function () { + self.showFilterMenu(); + }); + var btnSelectView = tabContent.querySelector(".btnSelectView"); + btnSelectView.addEventListener("click", function (e) { + libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), "List,Poster,PosterCard".split(",")); + }); + btnSelectView.addEventListener("layoutchange", function (e) { + var viewStyle = e.detail.viewStyle; + getPageData(tabContent).view = viewStyle; + libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle); + getQuery(tabContent).StartIndex = 0; + onViewStyleChange(); + reloadItems(tabContent); + }); + } + + initPage(tabContent); + onViewStyleChange(); + + self.renderTab = function () { + reloadItems(tabContent); + updateFilterControls(tabContent); + }; + + self.destroy = function () {}; + }; }); diff --git a/src/controllers/music/musicgenres.js b/src/controllers/music/musicgenres.js index f66afcdb20..ed1efc0a6a 100644 --- a/src/controllers/music/musicgenres.js +++ b/src/controllers/music/musicgenres.js @@ -1,91 +1,126 @@ -define(["libraryBrowser", "cardBuilder", "apphost", "imageLoader", "loading"], function(libraryBrowser, cardBuilder, appHost, imageLoader, loading) { +define(["libraryBrowser", "cardBuilder", "apphost", "imageLoader", "loading"], function (libraryBrowser, cardBuilder, appHost, imageLoader, loading) { "use strict"; - return function(view, params, tabContent) { + + return function (view, params, tabContent) { function getPageData() { - var key = getSavedQueryKey(), - pageData = data[key]; - return pageData || (pageData = data[key] = { - query: { - SortBy: "SortName", - SortOrder: "Ascending", - Recursive: !0, - Fields: "PrimaryImageAspectRatio,ItemCounts", - StartIndex: 0 - }, - view: libraryBrowser.getSavedView(key) || "Poster" - }, pageData.query.ParentId = params.topParentId, libraryBrowser.loadSavedQueryValues(key, pageData.query)), pageData + var key = getSavedQueryKey(); + var pageData = data[key]; + + if (!pageData) { + pageData = data[key] = { + query: { + SortBy: "SortName", + SortOrder: "Ascending", + Recursive: true, + Fields: "PrimaryImageAspectRatio,ItemCounts", + StartIndex: 0 + }, + view: libraryBrowser.getSavedView(key) || "Poster" + }; + pageData.query.ParentId = params.topParentId; + libraryBrowser.loadSavedQueryValues(key, pageData.query); + } + + return pageData; } function getQuery() { - return getPageData().query + return getPageData().query; } function getSavedQueryKey() { - return libraryBrowser.getSavedQueryKey("genres") + return libraryBrowser.getSavedQueryKey("genres"); } function getPromise() { loading.show(); var query = getQuery(); - return ApiClient.getGenres(ApiClient.getCurrentUserId(), query) + return ApiClient.getGenres(ApiClient.getCurrentUserId(), query); } function reloadItems(context, promise) { var query = getQuery(); - promise.then(function(result) { - var html = "", - viewStyle = self.getCurrentViewStyle(); - "Thumb" == viewStyle ? html = cardBuilder.getCardsHtml({ - items: result.Items, - shape: "backdrop", - preferThumb: !0, - context: "music", - centerText: !0, - overlayMoreButton: !0, - showTitle: !0 - }) : "ThumbCard" == viewStyle ? html = cardBuilder.getCardsHtml({ - items: result.Items, - shape: "backdrop", - preferThumb: !0, - context: "music", - cardLayout: !0, - showTitle: !0 - }) : "PosterCard" == viewStyle ? html = cardBuilder.getCardsHtml({ - items: result.Items, - shape: "auto", - context: "music", - cardLayout: !0, - showTitle: !0 - }) : "Poster" == viewStyle && (html = cardBuilder.getCardsHtml({ - items: result.Items, - shape: "auto", - context: "music", - centerText: !0, - overlayMoreButton: !0, - showTitle: !0 - })); + promise.then(function (result) { + var html = ""; + var viewStyle = self.getCurrentViewStyle(); + + if (viewStyle == "Thumb") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "backdrop", + preferThumb: true, + context: 'music', + centerText: true, + overlayMoreButton: true, + showTitle: true + }); + } else if (viewStyle == "ThumbCard") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "backdrop", + preferThumb: true, + context: 'music', + cardLayout: true, + showTitle: true, + }); + } else if (viewStyle == "PosterCard") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "auto", + context: 'music', + cardLayout: true, + showTitle: true, + }); + } else if (viewStyle == "Poster") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "auto", + context: 'music', + centerText: true, + overlayMoreButton: true, + showTitle: true + }); + } + var elem = context.querySelector("#items"); - elem.innerHTML = html, imageLoader.lazyChildren(elem), libraryBrowser.saveQueryValues(getSavedQueryKey(), query), loading.hide() - }) + elem.innerHTML = html; + imageLoader.lazyChildren(elem); + libraryBrowser.saveQueryValues(getSavedQueryKey(), query); + loading.hide(); + }); } function fullyReload() { - self.preRender(), self.renderTab() + self.preRender(); + self.renderTab(); } - var self = this, - data = {}; - self.getViewStyles = function() { - return "Poster,PosterCard,Thumb,ThumbCard".split(",") - }, self.getCurrentViewStyle = function() { - return getPageData(tabContent).view - }, self.setCurrentViewStyle = function(viewStyle) { - getPageData(tabContent).view = viewStyle, libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle), fullyReload() - }, self.enableViewSelection = !0; + + var self = this; + var data = {}; + + self.getViewStyles = function () { + return "Poster,PosterCard,Thumb,ThumbCard".split(","); + }; + + self.getCurrentViewStyle = function () { + return getPageData(tabContent).view; + }; + + self.setCurrentViewStyle = function (viewStyle) { + getPageData(tabContent).view = viewStyle; + libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle); + fullyReload(); + }; + + self.enableViewSelection = true; var promise; - self.preRender = function() { - promise = getPromise() - }, self.renderTab = function() { - reloadItems(tabContent, promise) - } - } -}); \ No newline at end of file + + self.preRender = function () { + promise = getPromise(); + }; + + self.renderTab = function () { + reloadItems(tabContent, promise); + }; + }; +}); diff --git a/src/controllers/music/musicplaylists.js b/src/controllers/music/musicplaylists.js index 511ace73a7..964896077b 100644 --- a/src/controllers/music/musicplaylists.js +++ b/src/controllers/music/musicplaylists.js @@ -1,64 +1,81 @@ -define(["libraryBrowser", "cardBuilder", "apphost", "imageLoader", "loading"], function(libraryBrowser, cardBuilder, appHost, imageLoader, loading) { +define(["libraryBrowser", "cardBuilder", "apphost", "imageLoader", "loading"], function (libraryBrowser, cardBuilder, appHost, imageLoader, loading) { "use strict"; - return function(view, params, tabContent) { + + return function (view, params, tabContent) { function getPageData() { - var key = getSavedQueryKey(), - pageData = data[key]; - return pageData || (pageData = data[key] = { - query: { - SortBy: "SortName", - SortOrder: "Ascending", - IncludeItemTypes: "Playlist", - Recursive: !0, - Fields: "PrimaryImageAspectRatio,SortName,CanDelete", - StartIndex: 0 - }, - view: libraryBrowser.getSavedView(key) || "Poster" - }, pageData.query.ParentId = params.topParentId, libraryBrowser.loadSavedQueryValues(key, pageData.query)), pageData + var key = getSavedQueryKey(); + var pageData = data[key]; + + if (!pageData) { + pageData = data[key] = { + query: { + SortBy: "SortName", + SortOrder: "Ascending", + IncludeItemTypes: "Playlist", + Recursive: true, + Fields: "PrimaryImageAspectRatio,SortName,CanDelete", + StartIndex: 0 + }, + view: libraryBrowser.getSavedView(key) || "Poster" + }; + pageData.query.ParentId = params.topParentId; + libraryBrowser.loadSavedQueryValues(key, pageData.query); + } + + return pageData; } function getQuery() { - return getPageData().query + return getPageData().query; } function getSavedQueryKey() { - return libraryBrowser.getSavedQueryKey("genres") + return libraryBrowser.getSavedQueryKey("genres"); } function getPromise() { loading.show(); var query = getQuery(); - return ApiClient.getItems(ApiClient.getCurrentUserId(), query) + return ApiClient.getItems(ApiClient.getCurrentUserId(), query); } function reloadItems(context, promise) { var query = getQuery(); - promise.then(function(result) { + promise.then(function (result) { var html = ""; html = cardBuilder.getCardsHtml({ items: result.Items, shape: "square", - showTitle: !0, - coverImage: !0, - centerText: !0, - overlayPlayButton: !0, - allowBottomPadding: !0, - cardLayout: !1 + showTitle: true, + coverImage: true, + centerText: true, + overlayPlayButton: true, + allowBottomPadding: true, + cardLayout: false }); var elem = context.querySelector("#items"); - elem.innerHTML = html, imageLoader.lazyChildren(elem), libraryBrowser.saveQueryValues(getSavedQueryKey(), query), loading.hide() - }) + elem.innerHTML = html; + imageLoader.lazyChildren(elem); + libraryBrowser.saveQueryValues(getSavedQueryKey(), query); + loading.hide(); + }); } - var self = this, - data = {}; - self.getCurrentViewStyle = function() { - return getPageData(tabContent).view + + var self = this; + var data = {}; + + self.getCurrentViewStyle = function () { + return getPageData(tabContent).view; }; + var promise; - self.preRender = function() { - promise = getPromise() - }, self.renderTab = function() { - reloadItems(tabContent, promise) - } - } -}); \ No newline at end of file + + self.preRender = function () { + promise = getPromise(); + }; + + self.renderTab = function () { + reloadItems(tabContent, promise); + }; + }; +}); diff --git a/src/controllers/music/musicrecommended.js b/src/controllers/music/musicrecommended.js index 5dee7c5f52..fc3371833d 100644 --- a/src/controllers/music/musicrecommended.js +++ b/src/controllers/music/musicrecommended.js @@ -1,49 +1,65 @@ -define(["browser", "layoutManager", "userSettings", "inputManager", "loading", "cardBuilder", "dom", "apphost", "imageLoader", "libraryMenu", "playbackManager", "mainTabsManager", "scrollStyles", "emby-itemscontainer", "emby-tabs", "emby-button", "flexStyles"], function(browser, layoutManager, userSettings, inputManager, loading, cardBuilder, dom, appHost, imageLoader, libraryMenu, playbackManager, mainTabsManager) { +define(["browser", "layoutManager", "userSettings", "inputManager", "loading", "cardBuilder", "dom", "apphost", "imageLoader", "libraryMenu", "playbackManager", "mainTabsManager", "scrollStyles", "emby-itemscontainer", "emby-tabs", "emby-button", "flexStyles"], function (browser, layoutManager, userSettings, inputManager, loading, cardBuilder, dom, appHost, imageLoader, libraryMenu, playbackManager, mainTabsManager) { "use strict"; function itemsPerRow() { var screenWidth = dom.getWindowSize().innerWidth; - return screenWidth >= 1920 ? 9 : screenWidth >= 1200 ? 12 : screenWidth >= 1e3 ? 10 : 8 + + if (screenWidth >= 1920) { + return 9; + } + + if (screenWidth >= 1200) { + return 12; + } + + if (screenWidth >= 1000) { + return 10; + } + + return 8; } function enableScrollX() { - return !layoutManager.desktop + return !layoutManager.desktop; } function getSquareShape() { - return enableScrollX() ? "overflowSquare" : "square" + return enableScrollX() ? "overflowSquare" : "square"; } function loadLatest(page, parentId) { loading.show(); - var userId = ApiClient.getCurrentUserId(), - options = { - IncludeItemTypes: "Audio", - Limit: enableScrollX() ? 3 * itemsPerRow() : 2 * itemsPerRow(), - Fields: "PrimaryImageAspectRatio,BasicSyncInfo", - ParentId: parentId, - ImageTypeLimit: 1, - EnableImageTypes: "Primary,Backdrop,Banner,Thumb", - EnableTotalRecordCount: !1 - }; - ApiClient.getJSON(ApiClient.getUrl("Users/" + userId + "/Items/Latest", options)).then(function(items) { - var elem = page.querySelector("#recentlyAddedSongs"), - supportsImageAnalysis = appHost.supports("imageanalysis"); - supportsImageAnalysis = !1, elem.innerHTML = cardBuilder.getCardsHtml({ + var userId = ApiClient.getCurrentUserId(); + var options = { + IncludeItemTypes: "Audio", + Limit: enableScrollX() ? 3 * itemsPerRow() : 2 * itemsPerRow(), + Fields: "PrimaryImageAspectRatio,BasicSyncInfo", + ParentId: parentId, + ImageTypeLimit: 1, + EnableImageTypes: "Primary,Backdrop,Banner,Thumb", + EnableTotalRecordCount: false + }; + ApiClient.getJSON(ApiClient.getUrl("Users/" + userId + "/Items/Latest", options)).then(function (items) { + var elem = page.querySelector("#recentlyAddedSongs"); + var supportsImageAnalysis = appHost.supports("imageanalysis"); + supportsImageAnalysis = false; + elem.innerHTML = cardBuilder.getCardsHtml({ items: items, - showUnplayedIndicator: !1, - showLatestItemsPopup: !1, + showUnplayedIndicator: false, + showLatestItemsPopup: false, shape: getSquareShape(), - showTitle: !0, - showParentTitle: !0, - lazy: !0, + showTitle: true, + showParentTitle: true, + lazy: true, centerText: !supportsImageAnalysis, overlayPlayButton: !supportsImageAnalysis, allowBottomPadding: !enableScrollX(), cardLayout: supportsImageAnalysis, - coverImage: !0 - }), imageLoader.lazyChildren(elem), loading.hide() - }) + coverImage: true + }); + imageLoader.lazyChildren(elem); + loading.hide(); + }); } function loadRecentlyPlayed(page, parentId) { @@ -52,34 +68,42 @@ define(["browser", "layoutManager", "userSettings", "inputManager", "loading", " SortOrder: "Descending", IncludeItemTypes: "Audio", Limit: itemsPerRow(), - Recursive: !0, + Recursive: true, Fields: "PrimaryImageAspectRatio,AudioInfo", Filters: "IsPlayed", ParentId: parentId, ImageTypeLimit: 1, EnableImageTypes: "Primary,Backdrop,Banner,Thumb", - EnableTotalRecordCount: !1 + EnableTotalRecordCount: false }; - ApiClient.getItems(ApiClient.getCurrentUserId(), options).then(function(result) { + ApiClient.getItems(ApiClient.getCurrentUserId(), options).then(function (result) { var elem = page.querySelector("#recentlyPlayed"); - result.Items.length ? elem.classList.remove("hide") : elem.classList.add("hide"); - var itemsContainer = elem.querySelector(".itemsContainer"), - supportsImageAnalysis = appHost.supports("imageanalysis"); - supportsImageAnalysis = !1, itemsContainer.innerHTML = cardBuilder.getCardsHtml({ + + if (result.Items.length) { + elem.classList.remove("hide"); + } else { + elem.classList.add("hide"); + } + + var itemsContainer = elem.querySelector(".itemsContainer"); + var supportsImageAnalysis = appHost.supports("imageanalysis"); + supportsImageAnalysis = false; + itemsContainer.innerHTML = cardBuilder.getCardsHtml({ items: result.Items, - showUnplayedIndicator: !1, + showUnplayedIndicator: false, shape: getSquareShape(), - showTitle: !0, - showParentTitle: !0, + showTitle: true, + showParentTitle: true, action: "instantmix", - lazy: !0, + lazy: true, centerText: !supportsImageAnalysis, overlayMoreButton: !supportsImageAnalysis, allowBottomPadding: !enableScrollX(), cardLayout: supportsImageAnalysis, - coverImage: !0 - }), imageLoader.lazyChildren(itemsContainer) - }) + coverImage: true + }); + imageLoader.lazyChildren(itemsContainer); + }); } function loadFrequentlyPlayed(page, parentId) { @@ -88,40 +112,53 @@ define(["browser", "layoutManager", "userSettings", "inputManager", "loading", " SortOrder: "Descending", IncludeItemTypes: "Audio", Limit: itemsPerRow(), - Recursive: !0, + Recursive: true, Fields: "PrimaryImageAspectRatio,AudioInfo", Filters: "IsPlayed", ParentId: parentId, ImageTypeLimit: 1, EnableImageTypes: "Primary,Backdrop,Banner,Thumb", - EnableTotalRecordCount: !1 + EnableTotalRecordCount: false }; - ApiClient.getItems(ApiClient.getCurrentUserId(), options).then(function(result) { + ApiClient.getItems(ApiClient.getCurrentUserId(), options).then(function (result) { var elem = page.querySelector("#topPlayed"); - result.Items.length ? elem.classList.remove("hide") : elem.classList.add("hide"); - var itemsContainer = elem.querySelector(".itemsContainer"), - supportsImageAnalysis = appHost.supports("imageanalysis"); - supportsImageAnalysis = !1, itemsContainer.innerHTML = cardBuilder.getCardsHtml({ + + if (result.Items.length) { + elem.classList.remove("hide"); + } else { + elem.classList.add("hide"); + } + + var itemsContainer = elem.querySelector(".itemsContainer"); + var supportsImageAnalysis = appHost.supports("imageanalysis"); + supportsImageAnalysis = false; + itemsContainer.innerHTML = cardBuilder.getCardsHtml({ items: result.Items, - showUnplayedIndicator: !1, + showUnplayedIndicator: false, shape: getSquareShape(), - showTitle: !0, - showParentTitle: !0, + showTitle: true, + showParentTitle: true, action: "instantmix", - lazy: !0, + lazy: true, centerText: !supportsImageAnalysis, overlayMoreButton: !supportsImageAnalysis, allowBottomPadding: !enableScrollX(), cardLayout: supportsImageAnalysis, - coverImage: !0 - }), imageLoader.lazyChildren(itemsContainer) - }) + coverImage: true + }); + imageLoader.lazyChildren(itemsContainer); + }); } function loadSuggestionsTab(page, tabContent, parentId) { - console.log("loadSuggestionsTab"), loadLatest(tabContent, parentId), loadRecentlyPlayed(tabContent, parentId), loadFrequentlyPlayed(tabContent, parentId), require(["components/favoriteitems"], function(favoriteItems) { - favoriteItems.render(tabContent, ApiClient.getCurrentUserId(), parentId, ["favoriteArtists", "favoriteAlbums", "favoriteSongs"]) - }) + console.log("loadSuggestionsTab"); + loadLatest(tabContent, parentId); + loadRecentlyPlayed(tabContent, parentId); + loadFrequentlyPlayed(tabContent, parentId); + + require(["components/favoriteitems"], function (favoriteItems) { + favoriteItems.render(tabContent, ApiClient.getCurrentUserId(), parentId, ["favoriteArtists", "favoriteAlbums", "favoriteSongs"]); + }); } function getTabs() { @@ -142,135 +179,227 @@ define(["browser", "layoutManager", "userSettings", "inputManager", "loading", " }, { name: Globalize.translate("ButtonSearch"), cssClass: "searchTabButton" - }] + }]; } function getDefaultTabIndex(folderId) { switch (userSettings.get("landing-" + folderId)) { case "albums": return 1; + case "albumartists": return 2; + case "artists": return 3; + case "playlists": return 4; + case "songs": return 5; + case "genres": return 6; + default: - return 0 + return 0; } } - return function(view, params) { + + return function (view, params) { function reload() { loading.show(); var tabContent = view.querySelector(".pageTabContent[data-index='0']"); - loadSuggestionsTab(view, tabContent, params.topParentId) + loadSuggestionsTab(view, tabContent, params.topParentId); } function enableScrollX() { - return browser.mobile + return browser.mobile; } function setScrollClasses(elem, scrollX) { - scrollX ? (elem.classList.add("hiddenScrollX"), layoutManager.tv && elem.classList.add("smoothScrollX"), elem.classList.add("scrollX"), elem.classList.remove("vertical-wrap")) : (elem.classList.remove("hiddenScrollX"), elem.classList.remove("smoothScrollX"), elem.classList.remove("scrollX"), elem.classList.add("vertical-wrap")) + if (scrollX) { + elem.classList.add("hiddenScrollX"); + + if (layoutManager.tv) { + elem.classList.add("smoothScrollX"); + } + + elem.classList.add("scrollX"); + elem.classList.remove("vertical-wrap"); + } else { + elem.classList.remove("hiddenScrollX"); + elem.classList.remove("smoothScrollX"); + elem.classList.remove("scrollX"); + elem.classList.add("vertical-wrap"); + } } function onBeforeTabChange(e) { - preLoadTab(view, parseInt(e.detail.selectedTabIndex)) + preLoadTab(view, parseInt(e.detail.selectedTabIndex)); } function onTabChange(e) { - loadTab(view, parseInt(e.detail.selectedTabIndex)) + loadTab(view, parseInt(e.detail.selectedTabIndex)); } function getTabContainers() { - return view.querySelectorAll(".pageTabContent") + return view.querySelectorAll(".pageTabContent"); } function initTabs() { - mainTabsManager.setTabs(view, currentTabIndex, getTabs, getTabContainers, onBeforeTabChange, onTabChange) + mainTabsManager.setTabs(view, currentTabIndex, getTabs, getTabContainers, onBeforeTabChange, onTabChange); } function getTabController(page, index, callback) { var depends = []; + switch (index) { case 0: break; + case 1: depends.push("controllers/music/musicalbums"); break; + case 2: case 3: depends.push("controllers/music/musicartists"); break; + case 4: depends.push("controllers/music/musicplaylists"); break; + case 5: depends.push("controllers/music/songs"); break; + case 6: depends.push("controllers/music/musicgenres"); break; + case 7: - depends.push("scripts/searchtab") + depends.push("scripts/searchtab"); } - require(depends, function(controllerFactory) { + + require(depends, function (controllerFactory) { var tabContent; - 0 == index && (tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"), self.tabContent = tabContent); + + if (0 == index) { + tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"); + self.tabContent = tabContent; + } + var controller = tabControllers[index]; - controller || (tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"), controller = 0 === index ? self : 7 === index ? new controllerFactory(view, tabContent, { - collectionType: "music", - parentId: params.topParentId - }) : new controllerFactory(view, params, tabContent), 2 == index ? controller.mode = "albumartists" : 3 == index && (controller.mode = "artists"), tabControllers[index] = controller, controller.initTab && controller.initTab()), callback(controller) - }) + + if (!controller) { + tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"); + + if (index === 0) { + controller = self; + } else if (index === 7) { + controller = new controllerFactory(view, tabContent, { + collectionType: "music", + parentId: params.topParentId + }); + } else { + controller = new controllerFactory(view, params, tabContent); + } + + if (index == 2) { + controller.mode = "albumartists"; + } else if (index == 3) { + controller.mode = "artists"; + } + + tabControllers[index] = controller; + if (controller.initTab) { + controller.initTab(); + } + } + + callback(controller); + }); } function preLoadTab(page, index) { - getTabController(page, index, function(controller) { - -1 == renderedTabs.indexOf(index) && controller.preRender && controller.preRender() - }) + getTabController(page, index, function (controller) { + if (renderedTabs.indexOf(index) == -1 && controller.preRender) { + controller.preRender(); + } + }); } function loadTab(page, index) { - currentTabIndex = index, getTabController(page, index, function(controller) { - initialTabIndex = null, -1 == renderedTabs.indexOf(index) && (renderedTabs.push(index), controller.renderTab()) - }) + currentTabIndex = index; + getTabController(page, index, function (controller) { + initialTabIndex = null; + + if (renderedTabs.indexOf(index) == -1) { + renderedTabs.push(index); + controller.renderTab(); + } + }); } function onInputCommand(e) { switch (e.detail.command) { case "search": - e.preventDefault(), Dashboard.navigate("search.html?collectionType=music&parentId=" + params.topParentId) + e.preventDefault(); + Dashboard.navigate("search.html?collectionType=music&parentId=" + params.topParentId); } } - var isViewRestored, self = this, - currentTabIndex = parseInt(params.tab || getDefaultTabIndex(params.topParentId)), - initialTabIndex = currentTabIndex; - self.initTab = function() { - for (var tabContent = view.querySelector(".pageTabContent[data-index='0']"), containers = tabContent.querySelectorAll(".itemsContainer"), i = 0, length = containers.length; i < length; i++) setScrollClasses(containers[i], enableScrollX()) - }, self.renderTab = function() { - reload() - }; - var tabControllers = [], - renderedTabs = []; - view.addEventListener("viewshow", function(e) { - if (isViewRestored = e.detail.isRestored, initTabs(), !view.getAttribute("data-title")) { - var parentId = params.topParentId; - parentId ? ApiClient.getItem(ApiClient.getCurrentUserId(), parentId).then(function(item) { - view.setAttribute("data-title", item.Name), libraryMenu.setTitle(item.Name) - }) : (view.setAttribute("data-title", Globalize.translate("TabMusic")), libraryMenu.setTitle(Globalize.translate("TabMusic"))) + + var isViewRestored; + var self = this; + var currentTabIndex = parseInt(params.tab || getDefaultTabIndex(params.topParentId)); + var initialTabIndex = currentTabIndex; + + self.initTab = function () { + var tabContent = view.querySelector(".pageTabContent[data-index='0']"); + var containers = tabContent.querySelectorAll(".itemsContainer"); + + for (var i = 0, length = containers.length; i < length; i++) { + setScrollClasses(containers[i], enableScrollX()); } - inputManager.on(window, onInputCommand) - }), view.addEventListener("viewbeforehide", function(e) { - inputManager.off(window, onInputCommand) - }), view.addEventListener("viewdestroy", function(e) { - tabControllers.forEach(function(t) { - t.destroy && t.destroy() - }) - }) - } -}); \ No newline at end of file + }; + + self.renderTab = function () { + reload(); + }; + + var tabControllers = []; + var renderedTabs = []; + view.addEventListener("viewshow", function (e) { + isViewRestored = e.detail.isRestored; + initTabs(); + if (!view.getAttribute("data-title")) { + var parentId = params.topParentId; + + if (parentId) { + ApiClient.getItem(ApiClient.getCurrentUserId(), parentId).then(function (item) { + view.setAttribute("data-title", item.Name); + libraryMenu.setTitle(item.Name); + }); + } else { + view.setAttribute("data-title", Globalize.translate("TabMusic")); + libraryMenu.setTitle(Globalize.translate("TabMusic")); + } + } + + inputManager.on(window, onInputCommand); + }); + view.addEventListener("viewbeforehide", function (e) { + inputManager.off(window, onInputCommand); + }); + view.addEventListener("viewdestroy", function (e) { + tabControllers.forEach(function (t) { + if (t.destroy) { + t.destroy(); + } + }); + }); + }; +}); diff --git a/src/controllers/music/songs.js b/src/controllers/music/songs.js index f03abe75ff..4806195edd 100644 --- a/src/controllers/music/songs.js +++ b/src/controllers/music/songs.js @@ -1,135 +1,185 @@ -define(["events", "libraryBrowser", "imageLoader", "listView", "loading", "emby-itemscontainer"], function(events, libraryBrowser, imageLoader, listView, loading) { +define(["events", "libraryBrowser", "imageLoader", "listView", "loading", "emby-itemscontainer"], function (events, libraryBrowser, imageLoader, listView, loading) { "use strict"; - return function(view, params, tabContent) { + + return function (view, params, tabContent) { function getPageData(context) { - var key = getSavedQueryKey(context), - pageData = data[key]; - return pageData || (pageData = data[key] = { - query: { - SortBy: "Album,SortName", - SortOrder: "Ascending", - IncludeItemTypes: "Audio", - Recursive: !0, - Fields: "AudioInfo,ParentId", - Limit: 100, - StartIndex: 0, - ImageTypeLimit: 1, - EnableImageTypes: "Primary" - } - }, pageData.query.ParentId = params.topParentId, libraryBrowser.loadSavedQueryValues(key, pageData.query)), pageData + var key = getSavedQueryKey(context); + var pageData = data[key]; + + if (!pageData) { + pageData = data[key] = { + query: { + SortBy: "Album,SortName", + SortOrder: "Ascending", + IncludeItemTypes: "Audio", + Recursive: true, + Fields: "AudioInfo,ParentId", + Limit: 100, + StartIndex: 0, + ImageTypeLimit: 1, + EnableImageTypes: "Primary" + } + }; + pageData.query.ParentId = params.topParentId; + libraryBrowser.loadSavedQueryValues(key, pageData.query); + } + + return pageData; } function getQuery(context) { - return getPageData(context).query + return getPageData(context).query; } function getSavedQueryKey(context) { - return context.savedQueryKey || (context.savedQueryKey = libraryBrowser.getSavedQueryKey("songs")), context.savedQueryKey + if (!context.savedQueryKey) { + context.savedQueryKey = libraryBrowser.getSavedQueryKey("songs"); + } + + return context.savedQueryKey; } function reloadItems(page) { loading.show(); isLoading = true; var query = getQuery(page); - ApiClient.getItems(Dashboard.getCurrentUserId(), query).then(function(result) { + ApiClient.getItems(Dashboard.getCurrentUserId(), query).then(function (result) { function onNextPageClick() { - if (isLoading) return; - query.StartIndex += query.Limit, reloadItems(tabContent) + if (isLoading) { + return; + } + + query.StartIndex += query.Limit; + reloadItems(tabContent); } function onPreviousPageClick() { - if (isLoading) return; - query.StartIndex -= query.Limit, reloadItems(tabContent) + if (isLoading) { + return; + } + + query.StartIndex -= query.Limit; + reloadItems(tabContent); } + window.scrollTo(0, 0); - var i, length, pagingHtml = libraryBrowser.getQueryPagingHtml({ - startIndex: query.StartIndex, - limit: query.Limit, - totalRecordCount: result.TotalRecordCount, - showLimit: !1, - updatePageSizeSetting: !1, - addLayoutButton: !1, - sortButton: !1, - filterButton: !1 - }), - html = listView.getListViewHtml({ - items: result.Items, - action: "playallfromhere", - smallIcon: !0, - artist: !0, - addToListButton: !0 - }), - elems = tabContent.querySelectorAll(".paging"); - for (i = 0, length = elems.length; i < length; i++) elems[i].innerHTML = pagingHtml; - for (elems = tabContent.querySelectorAll(".btnNextPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onNextPageClick); - for (elems = tabContent.querySelectorAll(".btnPreviousPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onPreviousPageClick); + var i; + var length; + var pagingHtml = libraryBrowser.getQueryPagingHtml({ + startIndex: query.StartIndex, + limit: query.Limit, + totalRecordCount: result.TotalRecordCount, + showLimit: false, + updatePageSizeSetting: false, + addLayoutButton: false, + sortButton: false, + filterButton: false + }); + var html = listView.getListViewHtml({ + items: result.Items, + action: "playallfromhere", + smallIcon: true, + artist: true, + addToListButton: true + }); + var elems = tabContent.querySelectorAll(".paging"); + + for (i = 0, length = elems.length; i < length; i++) { + elems[i].innerHTML = pagingHtml; + } + + elems = tabContent.querySelectorAll(".btnNextPage"); + for (i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener("click", onNextPageClick); + } + + elems = tabContent.querySelectorAll(".btnPreviousPage"); + for (i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener("click", onPreviousPageClick); + } + var itemsContainer = tabContent.querySelector(".itemsContainer"); itemsContainer.innerHTML = html; imageLoader.lazyChildren(itemsContainer); libraryBrowser.saveQueryValues(getSavedQueryKey(page), query); loading.hide(); isLoading = false; - }) + }); } - var self = this, - data = {}, - isLoading = false; - self.showFilterMenu = function() { - require(["components/filterdialog/filterdialog"], function(filterDialogFactory) { - var filterDialog = new filterDialogFactory({ - query: getQuery(tabContent), - mode: "songs", - serverId: ApiClient.serverId() - }); - events.on(filterDialog, "filterchange", function() { - getQuery(tabContent).StartIndex = 0, reloadItems(tabContent) - }), filterDialog.show() - }) - }, self.getCurrentViewStyle = function() { - return getPageData(tabContent).view - }, - function(tabContent) { - tabContent.querySelector(".btnFilter").addEventListener("click", function() { - self.showFilterMenu() - }), tabContent.querySelector(".btnSort").addEventListener("click", function(e) { - libraryBrowser.showSortMenu({ - items: [{ - name: Globalize.translate("OptionTrackName"), - id: "Name" - }, { - name: Globalize.translate("OptionAlbum"), - id: "Album,SortName" - }, { - name: Globalize.translate("OptionAlbumArtist"), - id: "AlbumArtist,Album,SortName" - }, { - name: Globalize.translate("OptionArtist"), - id: "Artist,Album,SortName" - }, { - name: Globalize.translate("OptionDateAdded"), - id: "DateCreated,SortName" - }, { - name: Globalize.translate("OptionDatePlayed"), - id: "DatePlayed,SortName" - }, { - name: Globalize.translate("OptionPlayCount"), - id: "PlayCount,SortName" - }, { - name: Globalize.translate("OptionReleaseDate"), - id: "PremiereDate,AlbumArtist,Album,SortName" - }, { - name: Globalize.translate("OptionRuntime"), - id: "Runtime,AlbumArtist,Album,SortName" - }], - callback: function() { - getQuery(tabContent).StartIndex = 0, reloadItems(tabContent) - }, - query: getQuery(tabContent), - button: e.target - }) - }) - }(tabContent), self.renderTab = function() { - reloadItems(tabContent) - }, self.destroy = function() {} - } + + var self = this; + var data = {}; + var isLoading = false; + + self.showFilterMenu = function () { + require(["components/filterdialog/filterdialog"], function (filterDialogFactory) { + var filterDialog = new filterDialogFactory({ + query: getQuery(tabContent), + mode: "songs", + serverId: ApiClient.serverId() + }); + events.on(filterDialog, "filterchange", function () { + getQuery(tabContent).StartIndex = 0; + reloadItems(tabContent); + }); + filterDialog.show(); + }); + }; + + self.getCurrentViewStyle = function () { + return getPageData(tabContent).view; + }; + + function initPage(tabContent) { + tabContent.querySelector(".btnFilter").addEventListener("click", function () { + self.showFilterMenu(); + }); + tabContent.querySelector(".btnSort").addEventListener("click", function (e) { + libraryBrowser.showSortMenu({ + items: [{ + name: Globalize.translate("OptionTrackName"), + id: "Name" + }, { + name: Globalize.translate("OptionAlbum"), + id: "Album,SortName" + }, { + name: Globalize.translate("OptionAlbumArtist"), + id: "AlbumArtist,Album,SortName" + }, { + name: Globalize.translate("OptionArtist"), + id: "Artist,Album,SortName" + }, { + name: Globalize.translate("OptionDateAdded"), + id: "DateCreated,SortName" + }, { + name: Globalize.translate("OptionDatePlayed"), + id: "DatePlayed,SortName" + }, { + name: Globalize.translate("OptionPlayCount"), + id: "PlayCount,SortName" + }, { + name: Globalize.translate("OptionReleaseDate"), + id: "PremiereDate,AlbumArtist,Album,SortName" + }, { + name: Globalize.translate("OptionRuntime"), + id: "Runtime,AlbumArtist,Album,SortName" + }], + callback: function () { + getQuery(tabContent).StartIndex = 0; + reloadItems(tabContent); + }, + query: getQuery(tabContent), + button: e.target + }); + }); + } + + initPage(tabContent); + + self.renderTab = function () { + reloadItems(tabContent); + }; + + self.destroy = function () {}; + }; }); diff --git a/src/controllers/notificationsetting.js b/src/controllers/notificationsetting.js index a9333ba5a3..70e6adaf61 100644 --- a/src/controllers/notificationsetting.js +++ b/src/controllers/notificationsetting.js @@ -1,85 +1,122 @@ -define(["jQuery", "emby-checkbox", "fnchecked"], function($) { +define(["jQuery", "emby-checkbox", "fnchecked"], function ($) { "use strict"; function fillItems(elem, items, cssClass, idPrefix, currentList, isEnabledList) { var html = '
'; - html += items.map(function(u) { - var isChecked = isEnabledList ? -1 != currentList.indexOf(u.Id) : -1 == currentList.indexOf(u.Id), - checkedHtml = isChecked ? ' checked="checked"' : ""; - return '" - }).join(""), html += "
", elem.html(html).trigger("create") + html += items.map(function (u) { + var isChecked = isEnabledList ? currentList.indexOf(u.Id) != -1 : currentList.indexOf(u.Id) == -1; + var checkedHtml = isChecked ? ' checked="checked"' : ""; + return '"; + }).join(""); + html += "
"; + elem.html(html).trigger("create"); } function reload(page) { - var type = getParameterByName("type"), - promise1 = ApiClient.getUsers(), - promise2 = ApiClient.getNamedConfiguration(notificationsConfigurationKey), - promise3 = ApiClient.getJSON(ApiClient.getUrl("Notifications/Types")), - promise4 = ApiClient.getJSON(ApiClient.getUrl("Notifications/Services")); - Promise.all([promise1, promise2, promise3, promise4]).then(function(responses) { - var users = responses[0], - notificationOptions = responses[1], - types = responses[2], - services = responses[3], - notificationConfig = notificationOptions.Options.filter(function(n) { - return n.Type == type - })[0], - typeInfo = types.filter(function(n) { - return n.Type == type - })[0] || {}; - typeInfo.IsBasedOnUserEvent ? $(".monitorUsers", page).show() : $(".monitorUsers", page).hide(), $(".notificationType", page).html(typeInfo.Name || "Unknown Notification"), notificationConfig || (notificationConfig = { - DisabledMonitorUsers: [], - SendToUsers: [], - DisabledServices: [], - SendToUserMode: "Admins" - }), fillItems($(".monitorUsersList", page), users, "chkMonitor", "chkMonitor", notificationConfig.DisabledMonitorUsers), fillItems($(".sendToUsersList", page), users, "chkSendTo", "chkSendTo", notificationConfig.SendToUsers, !0), fillItems($(".servicesList", page), services, "chkService", "chkService", notificationConfig.DisabledServices), $("#chkEnabled", page).checked(notificationConfig.Enabled || !1), $("#selectUsers", page).val(notificationConfig.SendToUserMode).trigger("change") - }) + var type = getParameterByName("type"); + var promise1 = ApiClient.getUsers(); + var promise2 = ApiClient.getNamedConfiguration(notificationsConfigurationKey); + var promise3 = ApiClient.getJSON(ApiClient.getUrl("Notifications/Types")); + var promise4 = ApiClient.getJSON(ApiClient.getUrl("Notifications/Services")); + Promise.all([promise1, promise2, promise3, promise4]).then(function (responses) { + var users = responses[0]; + var notificationOptions = responses[1]; + var types = responses[2]; + var services = responses[3]; + var notificationConfig = notificationOptions.Options.filter(function (n) { + return n.Type == type; + })[0]; + var typeInfo = types.filter(function (n) { + return n.Type == type; + })[0] || {}; + + if (typeInfo.IsBasedOnUserEvent) { + $(".monitorUsers", page).show(); + } else { + $(".monitorUsers", page).hide(); + } + + $(".notificationType", page).html(typeInfo.Name || "Unknown Notification"); + + if (!notificationConfig) { + notificationConfig = { + DisabledMonitorUsers: [], + SendToUsers: [], + DisabledServices: [], + SendToUserMode: "Admins" + }; + } + + fillItems($(".monitorUsersList", page), users, "chkMonitor", "chkMonitor", notificationConfig.DisabledMonitorUsers); + fillItems($(".sendToUsersList", page), users, "chkSendTo", "chkSendTo", notificationConfig.SendToUsers, true); + fillItems($(".servicesList", page), services, "chkService", "chkService", notificationConfig.DisabledServices); + $("#chkEnabled", page).checked(notificationConfig.Enabled || false); + $("#selectUsers", page).val(notificationConfig.SendToUserMode).trigger("change"); + }); } function save(page) { - var type = getParameterByName("type"), - promise1 = ApiClient.getNamedConfiguration(notificationsConfigurationKey), - promise2 = ApiClient.getJSON(ApiClient.getUrl("Notifications/Types")); - Promise.all([promise1, promise2]).then(function(responses) { - var notificationOptions = responses[0], - types = responses[1], - notificationConfig = notificationOptions.Options.filter(function(n) { - return n.Type == type - })[0]; - notificationConfig || (notificationConfig = { - Type: type - }, notificationOptions.Options.push(notificationConfig)); - types.filter(function(n) { - return n.Type == type + var type = getParameterByName("type"); + var promise1 = ApiClient.getNamedConfiguration(notificationsConfigurationKey); + var promise2 = ApiClient.getJSON(ApiClient.getUrl("Notifications/Types")); + Promise.all([promise1, promise2]).then(function (responses) { + var notificationOptions = responses[0]; + var types = responses[1]; + var notificationConfig = notificationOptions.Options.filter(function (n) { + return n.Type == type; })[0]; - notificationConfig.Enabled = $("#chkEnabled", page).checked(), notificationConfig.SendToUserMode = $("#selectUsers", page).val(), notificationConfig.DisabledMonitorUsers = $(".chkMonitor", page).get().filter(function(c) { - return !c.checked - }).map(function(c) { - return c.getAttribute("data-itemid") - }), notificationConfig.SendToUsers = $(".chkSendTo", page).get().filter(function(c) { - return c.checked - }).map(function(c) { - return c.getAttribute("data-itemid") - }), notificationConfig.DisabledServices = $(".chkService", page).get().filter(function(c) { - return !c.checked - }).map(function(c) { - return c.getAttribute("data-itemid") - }), ApiClient.updateNamedConfiguration(notificationsConfigurationKey, notificationOptions).then(function(r) { - Dashboard.processServerConfigurationUpdateResult(), Dashboard.navigate("notificationsettings.html") - }) - }) + + if (!notificationConfig) { + notificationConfig = { + Type: type + }; + notificationOptions.Options.push(notificationConfig); + } + + types.filter(function (n) { + return n.Type == type; + })[0]; + notificationConfig.Enabled = $("#chkEnabled", page).checked(); + notificationConfig.SendToUserMode = $("#selectUsers", page).val(); + notificationConfig.DisabledMonitorUsers = $(".chkMonitor", page).get().filter(function (c) { + return !c.checked; + }).map(function (c) { + return c.getAttribute("data-itemid"); + }); + notificationConfig.SendToUsers = $(".chkSendTo", page).get().filter(function (c) { + return c.checked; + }).map(function (c) { + return c.getAttribute("data-itemid"); + }); + notificationConfig.DisabledServices = $(".chkService", page).get().filter(function (c) { + return !c.checked; + }).map(function (c) { + return c.getAttribute("data-itemid"); + }); + ApiClient.updateNamedConfiguration(notificationsConfigurationKey, notificationOptions).then(function (r) { + Dashboard.processServerConfigurationUpdateResult(); + Dashboard.navigate("notificationsettings.html"); + }); + }); } function onSubmit() { - return save($(this).parents(".page")), !1 + save($(this).parents(".page")); + return false; } + var notificationsConfigurationKey = "notifications"; - $(document).on("pageinit", "#notificationSettingPage", function() { + $(document).on("pageinit", "#notificationSettingPage", function () { var page = this; - $("#selectUsers", page).on("change", function() { - "Custom" == this.value ? $(".selectCustomUsers", page).show() : $(".selectCustomUsers", page).hide() - }), $(".notificationSettingForm").off("submit", onSubmit).on("submit", onSubmit) - }).on("pageshow", "#notificationSettingPage", function() { - reload(this) - }) -}); \ No newline at end of file + $("#selectUsers", page).on("change", function () { + if ("Custom" == this.value) { + $(".selectCustomUsers", page).show(); + } else { + $(".selectCustomUsers", page).hide(); + } + }); + $(".notificationSettingForm").off("submit", onSubmit).on("submit", onSubmit); + }).on("pageshow", "#notificationSettingPage", function () { + reload(this); + }); +}); diff --git a/src/controllers/nowplayingpage.js b/src/controllers/nowplayingpage.js index 7f1b9b3f11..6fcdb2a79c 100644 --- a/src/controllers/nowplayingpage.js +++ b/src/controllers/nowplayingpage.js @@ -1,11 +1,22 @@ -define(["components/remotecontrol/remotecontrol", "libraryMenu", "emby-button"], function(remotecontrolFactory, libraryMenu) { +define(["components/remotecontrol/remotecontrol", "libraryMenu", "emby-button"], function (remotecontrolFactory, libraryMenu) { "use strict"; - return function(view, params) { - var remoteControl = new remotecontrolFactory; - remoteControl.init(view, view.querySelector(".remoteControlContent")), view.addEventListener("viewshow", function(e) { - libraryMenu.setTransparentMenu(!0), remoteControl && remoteControl.onShow() - }), view.addEventListener("viewbeforehide", function(e) { - libraryMenu.setTransparentMenu(!1), remoteControl && remoteControl.destroy() - }) - } -}); \ No newline at end of file + + return function (view, params) { + var remoteControl = new remotecontrolFactory(); + remoteControl.init(view, view.querySelector(".remoteControlContent")); + view.addEventListener("viewshow", function (e) { + libraryMenu.setTransparentMenu(true); + + if (remoteControl) { + remoteControl.onShow(); + } + }); + view.addEventListener("viewbeforehide", function (e) { + libraryMenu.setTransparentMenu(false); + + if (remoteControl) { + remoteControl.destroy(); + } + }); + }; +}); diff --git a/src/controllers/playbackconfiguration.js b/src/controllers/playbackconfiguration.js index 35a780949d..76c704f7eb 100644 --- a/src/controllers/playbackconfiguration.js +++ b/src/controllers/playbackconfiguration.js @@ -1,16 +1,25 @@ -define(["jQuery", "loading", "libraryMenu"], function($, loading, libraryMenu) { +define(["jQuery", "loading", "libraryMenu"], function ($, loading, libraryMenu) { "use strict"; function loadPage(page, config) { - $("#txtMinResumePct", page).val(config.MinResumePct), $("#txtMaxResumePct", page).val(config.MaxResumePct), $("#txtMinResumeDuration", page).val(config.MinResumeDurationSeconds), loading.hide() + $("#txtMinResumePct", page).val(config.MinResumePct); + $("#txtMaxResumePct", page).val(config.MaxResumePct); + $("#txtMinResumeDuration", page).val(config.MinResumeDurationSeconds); + loading.hide(); } function onSubmit() { loading.show(); var form = this; - return ApiClient.getServerConfiguration().then(function(config) { - config.MinResumePct = $("#txtMinResumePct", form).val(), config.MaxResumePct = $("#txtMaxResumePct", form).val(), config.MinResumeDurationSeconds = $("#txtMinResumeDuration", form).val(), ApiClient.updateServerConfiguration(config).then(Dashboard.processServerConfigurationUpdateResult) - }), !1 + ApiClient.getServerConfiguration().then(function (config) { + config.MinResumePct = $('#txtMinResumePct', form).val(); + config.MaxResumePct = $('#txtMaxResumePct', form).val(); + config.MinResumeDurationSeconds = $('#txtMinResumeDuration', form).val(); + + ApiClient.updateServerConfiguration(config).then(Dashboard.processServerConfigurationUpdateResult); + }); + + return false; } function getTabs() { @@ -23,17 +32,17 @@ define(["jQuery", "loading", "libraryMenu"], function($, loading, libraryMenu) { }, { href: "streamingsettings.html", name: Globalize.translate("TabStreaming") - }] + }]; } - $(document).on("pageinit", "#playbackConfigurationPage", function() { + $(document).on("pageinit", "#playbackConfigurationPage", function () { $(".playbackConfigurationForm").off("submit", onSubmit).on("submit", onSubmit) - }).on("pageshow", "#playbackConfigurationPage", function() { + }).on("pageshow", "#playbackConfigurationPage", function () { loading.show(); libraryMenu.setTabs("playback", 1, getTabs); var page = this; - ApiClient.getServerConfiguration().then(function(config) { - loadPage(page, config) - }) - }) -}); \ No newline at end of file + ApiClient.getServerConfiguration().then(function (config) { + loadPage(page, config); + }); + }); +}); diff --git a/src/controllers/scheduledtaskpage.js b/src/controllers/scheduledtaskpage.js index 32838c6de3..7dae03cb3d 100644 --- a/src/controllers/scheduledtaskpage.js +++ b/src/controllers/scheduledtaskpage.js @@ -1,111 +1,237 @@ -define(["jQuery", "loading", "datetime", "dom", "globalize", "emby-input", "emby-button", "emby-select"], function($, loading, datetime, dom, globalize) { +define(["jQuery", "loading", "datetime", "dom", "globalize", "emby-input", "emby-button", "emby-select"], function ($, loading, datetime, dom, globalize) { "use strict"; function fillTimeOfDay(select) { - for (var options = [], i = 0; i < 864e5; i += 9e5) options.push({ - name: ScheduledTaskPage.getDisplayTime(1e4 * i), - value: 1e4 * i - }); - select.innerHTML = options.map(function(o) { - return '" - }).join("") + + var options = []; + + for (var i = 0; i < 86400000; i += 900000) { + options.push({ + name: ScheduledTaskPage.getDisplayTime(i * 10000), + value: i * 10000 + }); + } + + select.innerHTML = options.map(function (o) { + return ''; + }).join(""); } - Array.prototype.remove = function(from, to) { + + Array.prototype.remove = function (from, to) { var rest = this.slice((to || from) + 1 || this.length); - return this.length = from < 0 ? this.length + from : from, this.push.apply(this, rest) + this.length = from < 0 ? this.length + from : from; + return this.push.apply(this, rest); }; + var ScheduledTaskPage = { - refreshScheduledTask: function(view) { + refreshScheduledTask: function (view) { loading.show(); var id = getParameterByName("id"); - ApiClient.getScheduledTask(id).then(function(task) { - ScheduledTaskPage.loadScheduledTask(view, task) - }) + ApiClient.getScheduledTask(id).then(function (task) { + ScheduledTaskPage.loadScheduledTask(view, task); + }); }, - loadScheduledTask: function(view, task) { - $(".taskName", view).html(task.Name), $("#pTaskDescription", view).html(task.Description), require(["listViewStyle"], function() { - ScheduledTaskPage.loadTaskTriggers(view, task) - }), loading.hide() + loadScheduledTask: function (view, task) { + $(".taskName", view).html(task.Name); + $("#pTaskDescription", view).html(task.Description); + + require(["listViewStyle"], function () { + ScheduledTaskPage.loadTaskTriggers(view, task); + }); + + loading.hide(); }, - loadTaskTriggers: function(context, task) { + loadTaskTriggers: function (context, task) { var html = ""; html += '
'; + for (var i = 0, length = task.Triggers.length; i < length; i++) { var trigger = task.Triggers[i]; - if (html += '
', html += 'schedule', trigger.MaxRuntimeTicks ? html += '
' : html += '
', html += "
" + ScheduledTaskPage.getTriggerFriendlyName(trigger) + "
", trigger.MaxRuntimeTicks) { + + html += '
'; + html += 'schedule'; + if (trigger.MaxRuntimeMs) { + html += '
'; + } else { + html += '
'; + } + html += "
" + ScheduledTaskPage.getTriggerFriendlyName(trigger) + "
"; + if (trigger.MaxRuntimeMs) { html += '
'; var hours = trigger.MaxRuntimeTicks / 36e9; - html += 1 == hours ? globalize.translate("ValueTimeLimitSingleHour") : globalize.translate("ValueTimeLimitMultiHour", hours), html += "
" + if (hours == 1) { + html += globalize.translate("ValueTimeLimitSingleHour"); + } else { + html += globalize.translate("ValueTimeLimitMultiHour", hours); + } + html += "
"; } - html += "
", html += '', html += "
" + + html += "
"; + html += ''; + html += "
"; } - html += "
", context.querySelector(".taskTriggers").innerHTML = html + + html += "
"; + context.querySelector(".taskTriggers").innerHTML = html; }, - getTriggerFriendlyName: function(trigger) { - if ("DailyTrigger" == trigger.Type) return "Daily at " + ScheduledTaskPage.getDisplayTime(trigger.TimeOfDayTicks); - if ("WeeklyTrigger" == trigger.Type) return trigger.DayOfWeek + "s at " + ScheduledTaskPage.getDisplayTime(trigger.TimeOfDayTicks); - if ("SystemEventTrigger" == trigger.Type && "WakeFromSleep" == trigger.SystemEvent) return "On wake from sleep"; - if ("IntervalTrigger" == trigger.Type) { + getTriggerFriendlyName: function (trigger) { + if ("DailyTrigger" == trigger.Type) { + return "Daily at " + ScheduledTaskPage.getDisplayTime(trigger.TimeOfDayTicks); + } + + if ("WeeklyTrigger" == trigger.Type) { + return trigger.DayOfWeek + "s at " + ScheduledTaskPage.getDisplayTime(trigger.TimeOfDayTicks); + } + + if ("SystemEventTrigger" == trigger.Type && "WakeFromSleep" == trigger.SystemEvent) { + return "On wake from sleep"; + } + + if (trigger.Type == "IntervalTrigger") { + var hours = trigger.IntervalTicks / 36e9; - return .25 == hours ? "Every 15 minutes" : .5 == hours ? "Every 30 minutes" : .75 == hours ? "Every 45 minutes" : 1 == hours ? "Every hour" : "Every " + hours + " hours" + + if (hours == .25) { + return "Every 15 minutes"; + } + if (hours == .5) { + return "Every 30 minutes"; + } + if (hours == .75) { + return "Every 45 minutes"; + } + if (hours == 1) { + return "Every hour"; + } + + return "Every " + hours + " hours"; } - return "StartupTrigger" == trigger.Type ? "On application startup" : trigger.Type + + if (trigger.Type == "StartupTrigger") { + return "On application startup"; + } + + return trigger.Type; }, - getDisplayTime: function(ticks) { - var ms = ticks / 1e4, - now = new Date; - return now.setHours(0, 0, 0, 0), now.setTime(now.getTime() + ms), datetime.getDisplayTime(now) + getDisplayTime: function (ticks) { + var ms = ticks / 1e4; + var now = new Date(); + now.setHours(0, 0, 0, 0); + now.setTime(now.getTime() + ms); + return datetime.getDisplayTime(now); }, - showAddTriggerPopup: function(view) { - $("#selectTriggerType", view).val("DailyTrigger"), view.querySelector("#selectTriggerType").dispatchEvent(new CustomEvent("change", {})), $("#popupAddTrigger", view).removeClass("hide") + showAddTriggerPopup: function (view) { + $("#selectTriggerType", view).val("DailyTrigger"); + view.querySelector("#selectTriggerType").dispatchEvent(new CustomEvent("change", {})); + $("#popupAddTrigger", view).removeClass("hide"); }, - confirmDeleteTrigger: function(view, index) { - require(["confirm"], function(confirm) { - confirm(globalize.translate("MessageDeleteTaskTrigger"), globalize.translate("HeaderDeleteTaskTrigger")).then(function() { - ScheduledTaskPage.deleteTrigger(view, index) - }) - }) + confirmDeleteTrigger: function (view, index) { + require(["confirm"], function (confirm) { + confirm(globalize.translate("MessageDeleteTaskTrigger"), globalize.translate("HeaderDeleteTaskTrigger")).then(function () { + ScheduledTaskPage.deleteTrigger(view, index); + }); + }); }, - deleteTrigger: function(view, index) { + deleteTrigger: function (view, index) { loading.show(); var id = getParameterByName("id"); - ApiClient.getScheduledTask(id).then(function(task) { - task.Triggers.remove(index), ApiClient.updateScheduledTaskTriggers(task.Id, task.Triggers).then(function() { - ScheduledTaskPage.refreshScheduledTask(view) - }) - }) + ApiClient.getScheduledTask(id).then(function (task) { + task.Triggers.remove(index); + ApiClient.updateScheduledTaskTriggers(task.Id, task.Triggers).then(function () { + ScheduledTaskPage.refreshScheduledTask(view); + }); + }); }, - refreshTriggerFields: function(page, triggerType) { - "DailyTrigger" == triggerType ? ($("#fldTimeOfDay", page).show(), $("#fldDayOfWeek", page).hide(), $("#fldSelectSystemEvent", page).hide(), $("#fldSelectInterval", page).hide(), $("#selectTimeOfDay", page).attr("required", "required")) : "WeeklyTrigger" == triggerType ? ($("#fldTimeOfDay", page).show(), $("#fldDayOfWeek", page).show(), $("#fldSelectSystemEvent", page).hide(), $("#fldSelectInterval", page).hide(), $("#selectTimeOfDay", page).attr("required", "required")) : "SystemEventTrigger" == triggerType ? ($("#fldTimeOfDay", page).hide(), $("#fldDayOfWeek", page).hide(), $("#fldSelectSystemEvent", page).show(), $("#fldSelectInterval", page).hide(), $("#selectTimeOfDay", page).removeAttr("required")) : "IntervalTrigger" == triggerType ? ($("#fldTimeOfDay", page).hide(), $("#fldDayOfWeek", page).hide(), $("#fldSelectSystemEvent", page).hide(), $("#fldSelectInterval", page).show(), $("#selectTimeOfDay", page).removeAttr("required")) : "StartupTrigger" == triggerType && ($("#fldTimeOfDay", page).hide(), $("#fldDayOfWeek", page).hide(), $("#fldSelectSystemEvent", page).hide(), $("#fldSelectInterval", page).hide(), $("#selectTimeOfDay", page).removeAttr("required")) + refreshTriggerFields: function (page, triggerType) { + if (triggerType == "DailyTrigger") { + $("#fldTimeOfDay", page).show(); + $("#fldDayOfWeek", page).hide(); + $("#fldSelectSystemEvent", page).hide(); + $("#fldSelectInterval", page).hide(); + $("#selectTimeOfDay", page).attr("required", "required"); + } else if (triggerType == "WeeklyTrigger") { + $("#fldTimeOfDay", page).show(); + $("#fldDayOfWeek", page).show(); + $("#fldSelectSystemEvent", page).hide(); + $("#fldSelectInterval", page).hide(); + $("#selectTimeOfDay", page).attr("required", "required"); + } else if (triggerType == "SystemEventTrigger") { + $("#fldTimeOfDay", page).hide(); + $("#fldDayOfWeek", page).hide(); + $("#fldSelectSystemEvent", page).show(); + $("#fldSelectInterval", page).hide(); + $("#selectTimeOfDay", page).removeAttr("required"); + } else if (triggerType == "IntervalTrigger") { + $("#fldTimeOfDay", page).hide(); + $("#fldDayOfWeek", page).hide(); + $("#fldSelectSystemEvent", page).hide(); + $("#fldSelectInterval", page).show(); + $("#selectTimeOfDay", page).removeAttr("required"); + } else if (triggerType == "StartupTrigger") { + $("#fldTimeOfDay", page).hide(); + $("#fldDayOfWeek", page).hide(); + $("#fldSelectSystemEvent", page).hide(); + $("#fldSelectInterval", page).hide(); + $("#selectTimeOfDay", page).removeAttr("required"); + } }, - getTriggerToAdd: function(page) { + getTriggerToAdd: function (page) { var trigger = { Type: $("#selectTriggerType", page).val() }; - "DailyTrigger" == trigger.Type ? trigger.TimeOfDayTicks = $("#selectTimeOfDay", page).val() : "WeeklyTrigger" == trigger.Type ? (trigger.DayOfWeek = $("#selectDayOfWeek", page).val(), trigger.TimeOfDayTicks = $("#selectTimeOfDay", page).val()) : "SystemEventTrigger" == trigger.Type ? trigger.SystemEvent = $("#selectSystemEvent", page).val() : "IntervalTrigger" == trigger.Type && (trigger.IntervalTicks = $("#selectInterval", page).val()); + + if (trigger.Type == "DailyTrigger") { + trigger.TimeOfDayTicks = $("#selectTimeOfDay", page).val(); + } else if (trigger.Type == "WeeklyTrigger") { + trigger.DayOfWeek = $("#selectDayOfWeek", page).val(); + trigger.TimeOfDayTicks = $("#selectTimeOfDay", page).val(); + } else if (trigger.Type == "SystemEventTrigger") { + trigger.SystemEvent = $("#selectSystemEvent", page).val(); + } else if (trigger.Type == "IntervalTrigger") { + trigger.IntervalTicks = $("#selectInterval", page).val(); + } + var timeLimit = $("#txtTimeLimit", page).val() || "0"; - return timeLimit = 36e5 * parseFloat(timeLimit), trigger.MaxRuntimeMs = timeLimit || null, trigger + timeLimit = parseFloat(timeLimit) * 3600000; + + trigger.MaxRuntimeMs = timeLimit || null; + + return trigger; } }; - return function(view, params) { + return function (view, params) { function onSubmit(e) { loading.show(); var id = getParameterByName("id"); - ApiClient.getScheduledTask(id).then(function(task) { - task.Triggers.push(ScheduledTaskPage.getTriggerToAdd(view)), ApiClient.updateScheduledTaskTriggers(task.Id, task.Triggers).then(function() { - $("#popupAddTrigger").addClass("hide"), ScheduledTaskPage.refreshScheduledTask(view) - }) - }), e.preventDefault() + ApiClient.getScheduledTask(id).then(function (task) { + task.Triggers.push(ScheduledTaskPage.getTriggerToAdd(view)); + ApiClient.updateScheduledTaskTriggers(task.Id, task.Triggers).then(function () { + $("#popupAddTrigger").addClass("hide"); + ScheduledTaskPage.refreshScheduledTask(view); + }); + }); + e.preventDefault(); } - view.querySelector(".addTriggerForm").addEventListener("submit", onSubmit), fillTimeOfDay(view.querySelector("#selectTimeOfDay")), $(view.querySelector("#popupAddTrigger").parentNode).trigger("create"), view.querySelector(".selectTriggerType").addEventListener("change", function() { - ScheduledTaskPage.refreshTriggerFields(view, this.value) - }), view.querySelector(".btnAddTrigger").addEventListener("click", function() { - ScheduledTaskPage.showAddTriggerPopup(view) - }), view.addEventListener("click", function(e) { + + view.querySelector(".addTriggerForm").addEventListener("submit", onSubmit); + fillTimeOfDay(view.querySelector("#selectTimeOfDay")); + $(view.querySelector("#popupAddTrigger").parentNode).trigger("create"); + view.querySelector(".selectTriggerType").addEventListener("change", function () { + ScheduledTaskPage.refreshTriggerFields(view, this.value); + }); + view.querySelector(".btnAddTrigger").addEventListener("click", function () { + ScheduledTaskPage.showAddTriggerPopup(view); + }); + view.addEventListener("click", function (e) { var btnDeleteTrigger = dom.parentWithClass(e.target, "btnDeleteTrigger"); - btnDeleteTrigger && ScheduledTaskPage.confirmDeleteTrigger(view, parseInt(btnDeleteTrigger.getAttribute("data-index"))) - }), view.addEventListener("viewshow", function() { - ScheduledTaskPage.refreshScheduledTask(view) - }) - } -}); \ No newline at end of file + + if (btnDeleteTrigger) { + ScheduledTaskPage.confirmDeleteTrigger(view, parseInt(btnDeleteTrigger.getAttribute("data-index"))); + } + }); + view.addEventListener("viewshow", function () { + ScheduledTaskPage.refreshScheduledTask(view); + }); + }; +}); diff --git a/src/controllers/searchpage.js b/src/controllers/searchpage.js index b188a8b318..b260ef5751 100644 --- a/src/controllers/searchpage.js +++ b/src/controllers/searchpage.js @@ -1,21 +1,36 @@ -define(["focusManager", "searchFields", "searchResults", "events"], function(focusManager, SearchFields, SearchResults, events) { +define(["focusManager", "searchFields", "searchResults", "events"], function (focusManager, SearchFields, SearchResults, events) { "use strict"; - return function(view, params) { + + return function (view, params) { function onSearch(e, value) { - self.searchResults.search(value) + self.searchResults.search(value); } + var self = this; - view.addEventListener("viewshow", function() { - self.searchFields || (self.searchFields = new SearchFields({ - element: view.querySelector(".searchFields") - }), self.searchResults = new SearchResults({ - element: view.querySelector(".searchResults"), - serverId: params.serverId || ApiClient.serverId(), - parentId: params.parentId, - collectionType: params.collectionType - }), events.on(self.searchFields, "search", onSearch)) - }), view.addEventListener("viewdestroy", function() { - self.searchFields && (self.searchFields.destroy(), self.searchFields = null), self.searchResults && (self.searchResults.destroy(), self.searchResults = null) - }) - } -}); \ No newline at end of file + view.addEventListener("viewshow", function () { + if (!self.searchFields) { + self.searchFields = new SearchFields({ + element: view.querySelector(".searchFields") + }); + self.searchResults = new SearchResults({ + element: view.querySelector(".searchResults"), + serverId: params.serverId || ApiClient.serverId(), + parentId: params.parentId, + collectionType: params.collectionType + }); + events.on(self.searchFields, "search", onSearch); + } + }); + view.addEventListener("viewdestroy", function () { + if (self.searchFields) { + self.searchFields.destroy(); + self.searchFields = null; + } + + if (self.searchResults) { + self.searchResults.destroy(); + self.searchResults = null; + } + }); + }; +}); diff --git a/src/controllers/selectserver.js b/src/controllers/selectserver.js index 385ab69ca2..80ecb13f00 100644 --- a/src/controllers/selectserver.js +++ b/src/controllers/selectserver.js @@ -1,50 +1,56 @@ -define(["loading", "appRouter", "layoutManager", "appSettings", "apphost", "focusManager", "connectionManager", "globalize", "actionsheet", "dom", "material-icons", "flexStyles", "emby-scroller", "emby-itemscontainer", "cardStyle", "emby-button"], function(loading, appRouter, layoutManager, appSettings, appHost, focusManager, connectionManager, globalize, actionSheet, dom) { +define(["loading", "appRouter", "layoutManager", "appSettings", "apphost", "focusManager", "connectionManager", "globalize", "actionsheet", "dom", "material-icons", "flexStyles", "emby-scroller", "emby-itemscontainer", "cardStyle", "emby-button"], function (loading, appRouter, layoutManager, appSettings, appHost, focusManager, connectionManager, globalize, actionSheet, dom) { "use strict"; function renderSelectServerItems(view, servers) { - var items = servers.map(function(server) { - return { - name: server.Name, - showIcon: !0, - icon: "", - cardType: "", - id: server.Id, - server: server - } + var items = servers.map(function (server) { + return { + name: server.Name, + showIcon: true, + icon: "", + cardType: "", + id: server.Id, + server: server + }; }); - var html = items.map(function(item) { - var cardImageContainer; - if (item.showIcon) { - cardImageContainer = '' + item.icon + ""; - } else { - cardImageContainer = '
'; - } - var cardBoxCssClass = "cardBox"; - if (layoutManager.tv) { - cardBoxCssClass += " cardBox-focustransform"; - } - var innerOpening = '
'; - var cardContainer = ''; - cardContainer += '
'; - return cardContainer; + var html = items.map(function (item) { + var cardImageContainer; + + if (item.showIcon) { + cardImageContainer = '' + item.icon + ""; + } else { + cardImageContainer = '
'; + } + + var cardBoxCssClass = "cardBox"; + + if (layoutManager.tv) { + cardBoxCssClass += " cardBox-focustransform"; + } + + var innerOpening = '
'; + var cardContainer = ''; + cardContainer += '
'; + return cardContainer; }).join(""); var itemsContainer = view.querySelector(".servers"); + if (!items.length) { html = '

' + globalize.translate("MessageNoServersAvailable") + "

"; } + itemsContainer.innerHTML = html; loading.hide(); } @@ -73,7 +79,7 @@ define(["loading", "appRouter", "layoutManager", "appSettings", "apphost", "focu } function alertTextWithOptions(options) { - require(["alert"], function(alert) { + require(["alert"], function (alert) { alert(options); }); } @@ -82,38 +88,42 @@ define(["loading", "appRouter", "layoutManager", "appSettings", "apphost", "focu alertText(globalize.translate("MessageUnableToConnectToServer"), globalize.translate("HeaderConnectionFailure")); } - return function(view, params) { + return function (view, params) { function connectToServer(server) { loading.show(); connectionManager.connectToServer(server, { enableAutoLogin: appSettings.enableAutoLogin() - }).then(function(result) { + }).then(function (result) { loading.hide(); var apiClient = result.ApiClient; + switch (result.State) { case "SignedIn": Dashboard.onServerChanged(apiClient.getCurrentUserId(), apiClient.accessToken(), apiClient); Dashboard.navigate("home.html"); break; + case "ServerSignIn": Dashboard.onServerChanged(null, null, apiClient); Dashboard.navigate("login.html?serverid=" + result.Servers[0].Id); break; + case "ServerUpdateNeeded": alertTextWithOptions({ text: globalize.translate("core#ServerUpdateNeeded", "https://github.com/jellyfin/jellyfin"), html: globalize.translate("core#ServerUpdateNeeded", 'https://github.com/jellyfin/jellyfin') }); break; + default: showServerConnectionFailure(); } - }) + }); } function deleteServer(server) { loading.show(); - connectionManager.deleteServer(server.Id).then(function() { + connectionManager.deleteServer(server.Id).then(function () { loading.hide(); loadServers(); }); @@ -132,20 +142,22 @@ define(["loading", "appRouter", "layoutManager", "appSettings", "apphost", "focu actionSheet.show({ items: menuItems, title: server.Name - }).then(function(id) { + }).then(function (id) { switch (id) { case "connect": connectToServer(server); break; + case "delete": deleteServer(server); } - }) + }); } function onServersRetrieved(result) { servers = result; renderSelectServerItems(view, result); + if (layoutManager.tv) { focusManager.autoFocus(view); } @@ -158,25 +170,29 @@ define(["loading", "appRouter", "layoutManager", "appSettings", "apphost", "focu var servers; updatePageStyle(view, params); - - view.addEventListener("viewshow", function(e) { + view.addEventListener("viewshow", function (e) { var isRestored = e.detail.isRestored; appRouter.setTitle(null); - if (!isRestored) loadServers(); + + if (!isRestored) { + loadServers(); + } }); - view.querySelector(".servers").addEventListener("click", function(e) { + view.querySelector(".servers").addEventListener("click", function (e) { var card = dom.parentWithClass(e.target, "card"); + if (card) { var url = card.getAttribute("data-url"); + if (url) { appRouter.show(url); } else { var id = card.getAttribute("data-id"); - onServerClick(servers.filter(function(s) { + onServerClick(servers.filter(function (s) { return s.Id === id; })[0]); } } - }) - } + }); + }; }); diff --git a/src/controllers/serveractivity.js b/src/controllers/serveractivity.js index 2b43215c93..fb3b8112dc 100644 --- a/src/controllers/serveractivity.js +++ b/src/controllers/serveractivity.js @@ -1,14 +1,31 @@ -define(["components/activitylog", "globalize"], function(ActivityLog, globalize) { +define(["components/activitylog", "globalize"], function (ActivityLog, globalize) { "use strict"; - return function(view, params) { + + return function (view, params) { var activityLog; - "false" !== params.useractivity ? (view.querySelector(".activityItems").setAttribute("data-useractivity", "true"), view.querySelector(".sectionTitle").innerHTML = globalize.translate("HeaderActivity")) : (view.querySelector(".activityItems").setAttribute("data-useractivity", "false"), view.querySelector(".sectionTitle").innerHTML = globalize.translate("Alerts")), view.addEventListener("viewshow", function() { - activityLog || (activityLog = new ActivityLog({ - serverId: ApiClient.serverId(), - element: view.querySelector(".activityItems") - })) - }), view.addEventListener("viewdestroy", function() { - activityLog && activityLog.destroy(), activityLog = null - }) - } -}); \ No newline at end of file + + if (params.useractivity !== "false") { + view.querySelector(".activityItems").setAttribute("data-useractivity", "true"); + view.querySelector(".sectionTitle").innerHTML = globalize.translate("HeaderActivity"); + } else { + view.querySelector(".activityItems").setAttribute("data-useractivity", "false"); + view.querySelector(".sectionTitle").innerHTML = globalize.translate("Alerts"); + } + + view.addEventListener("viewshow", function () { + if (!activityLog) { + activityLog = new ActivityLog({ + serverId: ApiClient.serverId(), + element: view.querySelector(".activityItems") + }); + } + }); + view.addEventListener("viewdestroy", function () { + if (activityLog) { + activityLog.destroy(); + } + + activityLog = null; + }); + }; +}); diff --git a/src/controllers/shows/episodes.js b/src/controllers/shows/episodes.js index 1f783631fb..42d9d89f7a 100644 --- a/src/controllers/shows/episodes.js +++ b/src/controllers/shows/episodes.js @@ -1,169 +1,233 @@ -define(["loading", "events", "libraryBrowser", "imageLoader", "listView", "cardBuilder", "emby-itemscontainer"], function(loading, events, libraryBrowser, imageLoader, listView, cardBuilder) { +define(["loading", "events", "libraryBrowser", "imageLoader", "listView", "cardBuilder", "emby-itemscontainer"], function (loading, events, libraryBrowser, imageLoader, listView, cardBuilder) { "use strict"; - return function(view, params, tabContent) { + + return function (view, params, tabContent) { function getPageData(context) { - var key = getSavedQueryKey(context), - pageData = data[key]; - return pageData || (pageData = data[key] = { - query: { - SortBy: "SeriesSortName,SortName", - SortOrder: "Ascending", - IncludeItemTypes: "Episode", - Recursive: !0, - Fields: "PrimaryImageAspectRatio,MediaSourceCount,UserData", - IsMissing: !1, - ImageTypeLimit: 1, - EnableImageTypes: "Primary,Backdrop,Thumb", - StartIndex: 0, - Limit: pageSize - }, - view: libraryBrowser.getSavedView(key) || "Poster" - }, pageData.query.ParentId = params.topParentId, libraryBrowser.loadSavedQueryValues(key, pageData.query)), pageData + var key = getSavedQueryKey(context); + var pageData = data[key]; + + if (!pageData) { + pageData = data[key] = { + query: { + SortBy: "SeriesSortName,SortName", + SortOrder: "Ascending", + IncludeItemTypes: "Episode", + Recursive: true, + Fields: "PrimaryImageAspectRatio,MediaSourceCount,UserData", + IsMissing: false, + ImageTypeLimit: 1, + EnableImageTypes: "Primary,Backdrop,Thumb", + StartIndex: 0, + Limit: pageSize + }, + view: libraryBrowser.getSavedView(key) || "Poster" + }; + pageData.query.ParentId = params.topParentId; + libraryBrowser.loadSavedQueryValues(key, pageData.query); + } + + return pageData; } function getQuery(context) { - return getPageData(context).query + return getPageData(context).query; } function getSavedQueryKey(context) { - return context.savedQueryKey || (context.savedQueryKey = libraryBrowser.getSavedQueryKey("episodes")), context.savedQueryKey + if (!context.savedQueryKey) { + context.savedQueryKey = libraryBrowser.getSavedQueryKey("episodes"); + } + + return context.savedQueryKey; } function onViewStyleChange() { - var viewStyle = self.getCurrentViewStyle(), - itemsContainer = tabContent.querySelector(".itemsContainer"); - "List" == viewStyle ? (itemsContainer.classList.add("vertical-list"), itemsContainer.classList.remove("vertical-wrap")) : (itemsContainer.classList.remove("vertical-list"), itemsContainer.classList.add("vertical-wrap")), itemsContainer.innerHTML = "" + var viewStyle = self.getCurrentViewStyle(); + var itemsContainer = tabContent.querySelector(".itemsContainer"); + + 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.innerHTML = ""; } function reloadItems(page) { loading.show(); isLoading = true; var query = getQuery(page); - ApiClient.getItems(Dashboard.getCurrentUserId(), query).then(function(result) { + ApiClient.getItems(Dashboard.getCurrentUserId(), query).then(function (result) { function onNextPageClick() { - if (isLoading) return; + if (isLoading) { + return; + } + query.StartIndex += query.Limit; - reloadItems(tabContent) + reloadItems(tabContent); } function onPreviousPageClick() { - if (isLoading) return; + if (isLoading) { + return; + } + query.StartIndex -= query.Limit; - reloadItems(tabContent) + reloadItems(tabContent); } window.scrollTo(0, 0); - var html, pagingHtml = libraryBrowser.getQueryPagingHtml({ - startIndex: query.StartIndex, - limit: query.Limit, - totalRecordCount: result.TotalRecordCount, - showLimit: !1, - updatePageSizeSetting: !1, - addLayoutButton: !1, - sortButton: !1, - filterButton: !1 - }), - viewStyle = self.getCurrentViewStyle(), - itemsContainer = tabContent.querySelector(".itemsContainer"); - html = "List" == viewStyle ? listView.getListViewHtml({ - items: result.Items, - sortBy: query.SortBy, - showParentTitle: !0 - }) : "PosterCard" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "backdrop", - showTitle: !0, - showParentTitle: !0, - scalable: !0, - cardLayout: !0 - }) : cardBuilder.getCardsHtml({ - items: result.Items, - shape: "backdrop", - showTitle: !0, - showParentTitle: !0, - overlayText: !1, - centerText: !0, - scalable: !0, - overlayPlayButton: !0 + var html; + var pagingHtml = libraryBrowser.getQueryPagingHtml({ + startIndex: query.StartIndex, + limit: query.Limit, + totalRecordCount: result.TotalRecordCount, + showLimit: false, + updatePageSizeSetting: false, + addLayoutButton: false, + sortButton: false, + filterButton: false }); - var i, length, elems; - for (elems = tabContent.querySelectorAll(".paging"), i = 0, length = elems.length; i < length; i++) + var viewStyle = self.getCurrentViewStyle(); + var itemsContainer = tabContent.querySelector(".itemsContainer"); + if (viewStyle == "List") { + html = listView.getListViewHtml({ + items: result.Items, + sortBy: query.SortBy, + showParentTitle: true + }); + } else if (viewStyle == "PosterCard") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "backdrop", + showTitle: true, + showParentTitle: true, + scalable: true, + cardLayout: true + }); + } else { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "backdrop", + showTitle: true, + showParentTitle: true, + overlayText: false, + centerText: true, + scalable: true, + overlayPlayButton: true + }); + } + var i; + var length; + var elems; + + elems = tabContent.querySelectorAll(".paging"); + for (i = 0, length = elems.length; i < length; i++) { elems[i].innerHTML = pagingHtml; - for (elems = tabContent.querySelectorAll(".btnNextPage"), i = 0, length = elems.length; i < length; i++) + } + + elems = tabContent.querySelectorAll(".btnNextPage"); + for (i = 0, length = elems.length; i < length; i++) { elems[i].addEventListener("click", onNextPageClick); - for (elems = tabContent.querySelectorAll(".btnPreviousPage"), i = 0, length = elems.length; i < length; i++) + } + + elems = tabContent.querySelectorAll(".btnPreviousPage"); + for (i = 0, length = elems.length; i < length; i++) { elems[i].addEventListener("click", onPreviousPageClick); + } + itemsContainer.innerHTML = html; imageLoader.lazyChildren(itemsContainer); libraryBrowser.saveQueryValues(getSavedQueryKey(page), query); loading.hide(); isLoading = false; - }) + }); } - var self = this, - pageSize = 100, - data = {}, - isLoading = false; - self.showFilterMenu = function() { - require(["components/filterdialog/filterdialog"], function(filterDialogFactory) { - var filterDialog = new filterDialogFactory({ - query: getQuery(tabContent), - mode: "episodes", - serverId: ApiClient.serverId() - }); - events.on(filterDialog, "filterchange", function() { - reloadItems(tabContent) - }), filterDialog.show() - }) - }, self.getCurrentViewStyle = function() { - return getPageData(tabContent).view - }, - function(tabContent) { - tabContent.querySelector(".btnFilter").addEventListener("click", function() { - self.showFilterMenu() - }), tabContent.querySelector(".btnSort").addEventListener("click", function(e) { - libraryBrowser.showSortMenu({ - items: [{ - name: Globalize.translate("OptionNameSort"), - id: "SeriesSortName,SortName" - }, { - name: Globalize.translate("OptionTvdbRating"), - id: "CommunityRating,SeriesSortName,SortName" - }, { - name: Globalize.translate("OptionDateAdded"), - id: "DateCreated,SeriesSortName,SortName" - }, { - name: Globalize.translate("OptionPremiereDate"), - id: "PremiereDate,SeriesSortName,SortName" - }, { - name: Globalize.translate("OptionDatePlayed"), - id: "DatePlayed,SeriesSortName,SortName" - }, { - name: Globalize.translate("OptionParentalRating"), - id: "OfficialRating,SeriesSortName,SortName" - }, { - name: Globalize.translate("OptionPlayCount"), - id: "PlayCount,SeriesSortName,SortName" - }, { - name: Globalize.translate("OptionRuntime"), - id: "Runtime,SeriesSortName,SortName" - }], - callback: function() { - reloadItems(tabContent) - }, - query: getQuery(tabContent), - button: e.target - }) + + var self = this; + var pageSize = 100; + var data = {}; + var isLoading = false; + + self.showFilterMenu = function () { + require(["components/filterdialog/filterdialog"], function (filterDialogFactory) { + var filterDialog = new filterDialogFactory({ + query: getQuery(tabContent), + mode: "episodes", + serverId: ApiClient.serverId() }); - var btnSelectView = tabContent.querySelector(".btnSelectView"); - btnSelectView.addEventListener("click", function(e) { - libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), "List,Poster,PosterCard".split(",")) - }), btnSelectView.addEventListener("layoutchange", function(e) { - var viewStyle = e.detail.viewStyle; - getPageData(tabContent).view = viewStyle, libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle), onViewStyleChange(), reloadItems(tabContent) - }) - }(tabContent), onViewStyleChange(), self.renderTab = function() { - reloadItems(tabContent) - }, self.destroy = function() {} - } + events.on(filterDialog, "filterchange", function () { + reloadItems(tabContent); + }); + filterDialog.show(); + }); + }; + + self.getCurrentViewStyle = function () { + return getPageData(tabContent).view; + }; + + function initPage(tabContent) { + tabContent.querySelector(".btnFilter").addEventListener("click", function () { + self.showFilterMenu(); + }); + tabContent.querySelector(".btnSort").addEventListener("click", function (e) { + libraryBrowser.showSortMenu({ + items: [{ + name: Globalize.translate("OptionNameSort"), + id: "SeriesSortName,SortName" + }, { + name: Globalize.translate("OptionTvdbRating"), + id: "CommunityRating,SeriesSortName,SortName" + }, { + name: Globalize.translate("OptionDateAdded"), + id: "DateCreated,SeriesSortName,SortName" + }, { + name: Globalize.translate("OptionPremiereDate"), + id: "PremiereDate,SeriesSortName,SortName" + }, { + name: Globalize.translate("OptionDatePlayed"), + id: "DatePlayed,SeriesSortName,SortName" + }, { + name: Globalize.translate("OptionParentalRating"), + id: "OfficialRating,SeriesSortName,SortName" + }, { + name: Globalize.translate("OptionPlayCount"), + id: "PlayCount,SeriesSortName,SortName" + }, { + name: Globalize.translate("OptionRuntime"), + id: "Runtime,SeriesSortName,SortName" + }], + callback: function () { + reloadItems(tabContent); + }, + query: getQuery(tabContent), + button: e.target + }); + }); + var btnSelectView = tabContent.querySelector(".btnSelectView"); + btnSelectView.addEventListener("click", function (e) { + libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), "List,Poster,PosterCard".split(",")); + }); + btnSelectView.addEventListener("layoutchange", function (e) { + var viewStyle = e.detail.viewStyle; + getPageData(tabContent).view = viewStyle; + libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle); + onViewStyleChange(); + reloadItems(tabContent); + }); + } + + initPage(tabContent); + onViewStyleChange(); + + self.renderTab = function () { + reloadItems(tabContent); + }; + + self.destroy = function () {}; + }; }); diff --git a/src/controllers/shows/tvgenres.js b/src/controllers/shows/tvgenres.js index e9559155e1..956b8fa6fa 100644 --- a/src/controllers/shows/tvgenres.js +++ b/src/controllers/shows/tvgenres.js @@ -1,139 +1,200 @@ -define(["layoutManager", "loading", "libraryBrowser", "cardBuilder", "lazyLoader", "apphost", "globalize", "appRouter", "dom", "emby-button"], function(layoutManager, loading, libraryBrowser, cardBuilder, lazyLoader, appHost, globalize, appRouter, dom) { +define(["layoutManager", "loading", "libraryBrowser", "cardBuilder", "lazyLoader", "apphost", "globalize", "appRouter", "dom", "emby-button"], function (layoutManager, loading, libraryBrowser, cardBuilder, lazyLoader, appHost, globalize, appRouter, dom) { "use strict"; - return function(view, params, tabContent) { + + return function (view, params, tabContent) { function getPageData() { - var key = getSavedQueryKey(), - pageData = data[key]; - return pageData || (pageData = data[key] = { - query: { - SortBy: "SortName", - SortOrder: "Ascending", - IncludeItemTypes: "Series", - Recursive: !0, - EnableTotalRecordCount: !1 - }, - view: "Poster" - }, pageData.query.ParentId = params.topParentId, libraryBrowser.loadSavedQueryValues(key, pageData.query)), pageData + var key = getSavedQueryKey(); + var pageData = data[key]; + + if (!pageData) { + pageData = data[key] = { + query: { + SortBy: "SortName", + SortOrder: "Ascending", + IncludeItemTypes: "Series", + Recursive: true, + EnableTotalRecordCount: false + }, + view: "Poster" + }; + pageData.query.ParentId = params.topParentId; + libraryBrowser.loadSavedQueryValues(key, pageData.query); + } + + return pageData; } function getQuery() { - return getPageData().query + return getPageData().query; } function getSavedQueryKey() { - return libraryBrowser.getSavedQueryKey("seriesgenres") + return libraryBrowser.getSavedQueryKey("seriesgenres"); } function getPromise() { loading.show(); var query = getQuery(); - return ApiClient.getGenres(ApiClient.getCurrentUserId(), query) + return ApiClient.getGenres(ApiClient.getCurrentUserId(), query); } function enableScrollX() { - return !layoutManager.desktop + return !layoutManager.desktop; } function getThumbShape() { - return enableScrollX() ? "overflowBackdrop" : "backdrop" + return enableScrollX() ? "overflowBackdrop" : "backdrop"; } function getPortraitShape() { - return enableScrollX() ? "overflowPortrait" : "portrait" + return enableScrollX() ? "overflowPortrait" : "portrait"; } function fillItemsContainer(elem) { - var id = elem.getAttribute("data-id"), - viewStyle = self.getCurrentViewStyle(), - limit = "Thumb" == viewStyle || "ThumbCard" == viewStyle ? 5 : 9; - enableScrollX() && (limit = 10); - var enableImageTypes = "Thumb" == viewStyle || "ThumbCard" == viewStyle ? "Primary,Backdrop,Thumb" : "Primary", - query = { - SortBy: "SortName", - SortOrder: "Ascending", - IncludeItemTypes: "Series", - Recursive: !0, - Fields: "PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo", - ImageTypeLimit: 1, - EnableImageTypes: enableImageTypes, - Limit: limit, - GenreIds: id, - EnableTotalRecordCount: !1, - ParentId: params.topParentId - }; - ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function(result) { + var id = elem.getAttribute("data-id"); + var viewStyle = self.getCurrentViewStyle(); + var limit = "Thumb" == viewStyle || "ThumbCard" == viewStyle ? 5 : 9; + + if (enableScrollX()) { + limit = 10; + } + + var enableImageTypes = "Thumb" == viewStyle || "ThumbCard" == viewStyle ? "Primary,Backdrop,Thumb" : "Primary"; + var query = { + SortBy: "SortName", + SortOrder: "Ascending", + IncludeItemTypes: "Series", + Recursive: true, + Fields: "PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo", + ImageTypeLimit: 1, + EnableImageTypes: enableImageTypes, + Limit: limit, + GenreIds: id, + EnableTotalRecordCount: false, + ParentId: params.topParentId + }; + ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function (result) { var supportsImageAnalysis = appHost.supports("imageanalysis"); - "Thumb" == viewStyle ? cardBuilder.buildCards(result.Items, { - itemsContainer: elem, - shape: getThumbShape(), - preferThumb: !0, - showTitle: !0, - scalable: !0, - centerText: !0, - overlayMoreButton: !0, - allowBottomPadding: !1 - }) : "ThumbCard" == viewStyle ? cardBuilder.buildCards(result.Items, { - itemsContainer: elem, - shape: getThumbShape(), - preferThumb: !0, - showTitle: !0, - scalable: !0, - centerText: !1, - cardLayout: !0, - showYear: !0 - }) : "PosterCard" == viewStyle ? cardBuilder.buildCards(result.Items, { - itemsContainer: elem, - shape: getPortraitShape(), - showTitle: !0, - scalable: !0, - centerText: !1, - cardLayout: !0, - showYear: !0 - }) : "Poster" == viewStyle && cardBuilder.buildCards(result.Items, { - itemsContainer: elem, - shape: getPortraitShape(), - scalable: !0, - overlayMoreButton: !0, - allowBottomPadding: !1 - }), result.Items.length >= query.Limit && tabContent.querySelector(".btnMoreFromGenre" + id + " i").classList.remove("hide") - }) + + if (viewStyle == "Thumb") { + cardBuilder.buildCards(result.Items, { + itemsContainer: elem, + shape: getThumbShape(), + preferThumb: true, + showTitle: true, + scalable: true, + centerText: true, + overlayMoreButton: true, + allowBottomPadding: false + }); + } else if (viewStyle == "ThumbCard") { + cardBuilder.buildCards(result.Items, { + itemsContainer: elem, + shape: getThumbShape(), + preferThumb: true, + showTitle: true, + scalable: true, + centerText: false, + cardLayout: true, + showYear: true + }); + } else if (viewStyle == "PosterCard") { + cardBuilder.buildCards(result.Items, { + itemsContainer: elem, + shape: getPortraitShape(), + showTitle: true, + scalable: true, + centerText: false, + cardLayout: true, + showYear: true + }); + } else if (viewStyle == "Poster") { + cardBuilder.buildCards(result.Items, { + itemsContainer: elem, + shape: getPortraitShape(), + scalable: true, + overlayMoreButton: true, + allowBottomPadding: false + }); + } + if (result.Items.length >= query.Limit) { + tabContent.querySelector(".btnMoreFromGenre" + id + " i").classList.remove("hide"); + } + }); } function reloadItems(context, promise) { var query = getQuery(); - promise.then(function(result) { - for (var elem = context.querySelector("#items"), html = "", items = result.Items, i = 0, length = items.length; i < length; i++) { + promise.then(function (result) { + var elem = context.querySelector("#items"); + var html = ""; + var items = result.Items; + + for (var i = 0, length = items.length; i < length; i++) { var item = items[i]; - if (html += '
', html += '", enableScrollX()) { + html += '
'; + html += '"; + if (enableScrollX()) { var scrollXClass = "scrollX hiddenScrollX"; - layoutManager.tv && (scrollXClass += " smoothScrollX"), html += '
' - } else html += '
'; - html += "
", html += "
" + if (layoutManager.tv) { + scrollXClass += "smoothScrollX"; + } + html += '
'; + } else { + html += '
'; + } + html += "
"; + html += "
"; } - elem.innerHTML = html, lazyLoader.lazyChildren(elem, fillItemsContainer), libraryBrowser.saveQueryValues(getSavedQueryKey(), query), loading.hide() - }) + + elem.innerHTML = html; + lazyLoader.lazyChildren(elem, fillItemsContainer); + libraryBrowser.saveQueryValues(getSavedQueryKey(), query); + loading.hide(); + }); } function fullyReload() { - self.preRender(), self.renderTab() + self.preRender(); + self.renderTab(); } - var self = this, - data = {}; - self.getViewStyles = function() { - return "Poster,PosterCard,Thumb,ThumbCard".split(",") - }, self.getCurrentViewStyle = function() { - return getPageData(tabContent).view - }, self.setCurrentViewStyle = function(viewStyle) { - getPageData(tabContent).view = viewStyle, libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle), fullyReload() - }, self.enableViewSelection = !0; + + var self = this; + var data = {}; + + self.getViewStyles = function () { + return "Poster,PosterCard,Thumb,ThumbCard".split(","); + }; + + self.getCurrentViewStyle = function () { + return getPageData(tabContent).view; + }; + + self.setCurrentViewStyle = function (viewStyle) { + getPageData(tabContent).view = viewStyle; + libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle); + fullyReload(); + }; + + self.enableViewSelection = true; var promise; - self.preRender = function() { - promise = getPromise() - }, self.renderTab = function() { - reloadItems(tabContent, promise) - } - } -}); \ No newline at end of file + + self.preRender = function () { + promise = getPromise(); + }; + + self.renderTab = function () { + reloadItems(tabContent, promise); + }; + }; +}); diff --git a/src/controllers/shows/tvlatest.js b/src/controllers/shows/tvlatest.js index 006f41e6ce..2a1ed56bf4 100644 --- a/src/controllers/shows/tvlatest.js +++ b/src/controllers/shows/tvlatest.js @@ -1,52 +1,60 @@ -define(["loading", "components/groupedcards", "cardBuilder", "apphost", "imageLoader"], function(loading, groupedcards, cardBuilder, appHost, imageLoader) { +define(["loading", "components/groupedcards", "cardBuilder", "apphost", "imageLoader"], function (loading, groupedcards, cardBuilder, appHost, imageLoader) { "use strict"; function getLatestPromise(context, params) { loading.show(); - var userId = ApiClient.getCurrentUserId(), - parentId = params.topParentId, - options = { - IncludeItemTypes: "Episode", - Limit: 30, - Fields: "PrimaryImageAspectRatio,BasicSyncInfo", - ParentId: parentId, - ImageTypeLimit: 1, - EnableImageTypes: "Primary,Backdrop,Thumb" - }; - return ApiClient.getJSON(ApiClient.getUrl("Users/" + userId + "/Items/Latest", options)) + var userId = ApiClient.getCurrentUserId(); + var parentId = params.topParentId; + var options = { + IncludeItemTypes: "Episode", + Limit: 30, + Fields: "PrimaryImageAspectRatio,BasicSyncInfo", + ParentId: parentId, + ImageTypeLimit: 1, + EnableImageTypes: "Primary,Backdrop,Thumb" + }; + return ApiClient.getJSON(ApiClient.getUrl("Users/" + userId + "/Items/Latest", options)); } function loadLatest(context, params, promise) { - promise.then(function(items) { + promise.then(function (items) { var html = ""; appHost.supports("imageanalysis"); html += cardBuilder.getCardsHtml({ items: items, shape: "backdrop", - preferThumb: !0, - showTitle: !0, - showSeriesYear: !0, - showParentTitle: !0, - overlayText: !1, - cardLayout: !1, - showUnplayedIndicator: !1, - showChildCountIndicator: !0, - centerText: !0, - lazy: !0, - overlayPlayButton: !0, + preferThumb: true, + showTitle: true, + showSeriesYear: true, + showParentTitle: true, + overlayText: false, + cardLayout: false, + showUnplayedIndicator: false, + showChildCountIndicator: true, + centerText: true, + lazy: true, + overlayPlayButton: true, lines: 2 }); var elem = context.querySelector("#latestEpisodes"); - elem.innerHTML = html, imageLoader.lazyChildren(elem), loading.hide() - }) + elem.innerHTML = html; + imageLoader.lazyChildren(elem); + loading.hide(); + }); } - return function(view, params, tabContent) { + + return function (view, params, tabContent) { var self = this; var latestPromise; - self.preRender = function() { - latestPromise = getLatestPromise(view, params) - }, self.renderTab = function() { - loadLatest(tabContent, params, latestPromise) - }, tabContent.querySelector("#latestEpisodes").addEventListener("click", groupedcards.onItemsContainerClick) - } -}); \ No newline at end of file + + self.preRender = function () { + latestPromise = getLatestPromise(view, params); + }; + + self.renderTab = function () { + loadLatest(tabContent, params, latestPromise); + }; + + tabContent.querySelector("#latestEpisodes").addEventListener("click", groupedcards.onItemsContainerClick); + }; +}); diff --git a/src/controllers/shows/tvrecommended.js b/src/controllers/shows/tvrecommended.js index 9de1461b3d..1386e76a31 100644 --- a/src/controllers/shows/tvrecommended.js +++ b/src/controllers/shows/tvrecommended.js @@ -1,4 +1,4 @@ -define(["events", "inputManager", "libraryMenu", "layoutManager", "loading", "dom", "userSettings", "cardBuilder", "playbackManager", "mainTabsManager", "scrollStyles", "emby-itemscontainer", "emby-button"], function(events, inputManager, libraryMenu, layoutManager, loading, dom, userSettings, cardBuilder, playbackManager, mainTabsManager) { +define(["events", "inputManager", "libraryMenu", "layoutManager", "loading", "dom", "userSettings", "cardBuilder", "playbackManager", "mainTabsManager", "scrollStyles", "emby-itemscontainer", "emby-button"], function (events, inputManager, libraryMenu, layoutManager, loading, dom, userSettings, cardBuilder, playbackManager, mainTabsManager) { "use strict"; function getTabs() { @@ -19,30 +19,51 @@ define(["events", "inputManager", "libraryMenu", "layoutManager", "loading", "do }, { name: Globalize.translate("ButtonSearch"), cssClass: "searchTabButton" - }] + }]; } function getDefaultTabIndex(folderId) { switch (userSettings.get("landing-" + folderId)) { case "suggestions": return 1; + case "latest": return 2; + case "favorites": return 1; + case "genres": return 4; + default: - return 0 + return 0; } } function setScrollClasses(elem, scrollX) { - scrollX ? (elem.classList.add("hiddenScrollX"), layoutManager.tv && elem.classList.add("smoothScrollX"), elem.classList.add("scrollX"), elem.classList.remove("vertical-wrap")) : (elem.classList.remove("hiddenScrollX"), elem.classList.remove("smoothScrollX"), elem.classList.remove("scrollX"), elem.classList.add("vertical-wrap")) + if (scrollX) { + elem.classList.add("hiddenScrollX"); + + if (layoutManager.tv) { + elem.classList.add("smoothScrollX"); + } + + elem.classList.add("scrollX"); + elem.classList.remove("vertical-wrap"); + } else { + elem.classList.remove("hiddenScrollX"); + elem.classList.remove("smoothScrollX"); + elem.classList.remove("scrollX"); + elem.classList.add("vertical-wrap"); + } } - return function(view, params) { + + return function (view, params) { function reload() { - loading.show(), loadResume(), loadNextUp() + loading.show(); + loadResume(); + loadNextUp(); } function loadNextUp() { @@ -52,178 +73,263 @@ define(["events", "inputManager", "libraryMenu", "layoutManager", "loading", "do UserId: ApiClient.getCurrentUserId(), ImageTypeLimit: 1, EnableImageTypes: "Primary,Backdrop,Thumb", - EnableTotalRecordCount: !1 + EnableTotalRecordCount: false }; - query.ParentId = libraryMenu.getTopParentId(), ApiClient.getNextUpEpisodes(query).then(function(result) { - result.Items.length ? view.querySelector(".noNextUpItems").classList.add("hide") : view.querySelector(".noNextUpItems").classList.remove("hide"); + query.ParentId = libraryMenu.getTopParentId(); + ApiClient.getNextUpEpisodes(query).then(function (result) { + if (result.Items.length) { + view.querySelector(".noNextUpItems").classList.add("hide"); + } else { + view.querySelector(".noNextUpItems").classList.remove("hide"); + } + var container = view.querySelector("#nextUpItems"); cardBuilder.buildCards(result.Items, { itemsContainer: container, - preferThumb: !0, + preferThumb: true, shape: "backdrop", - scalable: !0, - showTitle: !0, - showParentTitle: !0, - overlayText: !1, - centerText: !0, - overlayPlayButton: !0, - cardLayout: !1 - }), loading.hide() - }) + scalable: true, + showTitle: true, + showParentTitle: true, + overlayText: false, + centerText: true, + overlayPlayButton: true, + cardLayout: false + }); + loading.hide(); + }); } function enableScrollX() { - return !layoutManager.desktop + return !layoutManager.desktop; } function getThumbShape() { - return enableScrollX() ? "overflowBackdrop" : "backdrop" + return enableScrollX() ? "overflowBackdrop" : "backdrop"; } function loadResume() { - var parentId = libraryMenu.getTopParentId(), - screenWidth = dom.getWindowSize().innerWidth, - limit = screenWidth >= 1600 ? 5 : 6, - options = { - SortBy: "DatePlayed", - SortOrder: "Descending", - IncludeItemTypes: "Episode", - Filters: "IsResumable", - Limit: limit, - Recursive: !0, - Fields: "PrimaryImageAspectRatio,SeriesInfo,UserData,BasicSyncInfo", - ExcludeLocationTypes: "Virtual", - ParentId: parentId, - ImageTypeLimit: 1, - EnableImageTypes: "Primary,Backdrop,Thumb", - EnableTotalRecordCount: !1 - }; - ApiClient.getItems(ApiClient.getCurrentUserId(), options).then(function(result) { - result.Items.length ? view.querySelector("#resumableSection").classList.remove("hide") : view.querySelector("#resumableSection").classList.add("hide"); - var allowBottomPadding = !enableScrollX(), - container = view.querySelector("#resumableItems"); + var parentId = libraryMenu.getTopParentId(); + var screenWidth = dom.getWindowSize().innerWidth; + var limit = screenWidth >= 1600 ? 5 : 6; + var options = { + SortBy: "DatePlayed", + SortOrder: "Descending", + IncludeItemTypes: "Episode", + Filters: "IsResumable", + Limit: limit, + Recursive: true, + Fields: "PrimaryImageAspectRatio,SeriesInfo,UserData,BasicSyncInfo", + ExcludeLocationTypes: "Virtual", + ParentId: parentId, + ImageTypeLimit: 1, + EnableImageTypes: "Primary,Backdrop,Thumb", + EnableTotalRecordCount: false + }; + ApiClient.getItems(ApiClient.getCurrentUserId(), options).then(function (result) { + if (result.Items.length) { + view.querySelector("#resumableSection").classList.remove("hide"); + } else { + view.querySelector("#resumableSection").classList.add("hide"); + } + + var allowBottomPadding = !enableScrollX(); + var container = view.querySelector("#resumableItems"); cardBuilder.buildCards(result.Items, { itemsContainer: container, - preferThumb: !0, + preferThumb: true, shape: getThumbShape(), - scalable: !0, - showTitle: !0, - showParentTitle: !0, - overlayText: !1, - centerText: !0, - overlayPlayButton: !0, + scalable: true, + showTitle: true, + showParentTitle: true, + overlayText: false, + centerText: true, + overlayPlayButton: true, allowBottomPadding: allowBottomPadding, - cardLayout: !1 - }) - }) + cardLayout: false + }); + }); } function onBeforeTabChange(e) { - preLoadTab(view, parseInt(e.detail.selectedTabIndex)) + preLoadTab(view, parseInt(e.detail.selectedTabIndex)); } function onTabChange(e) { var newIndex = parseInt(e.detail.selectedTabIndex); - loadTab(view, newIndex) + loadTab(view, newIndex); } function getTabContainers() { - return view.querySelectorAll(".pageTabContent") + return view.querySelectorAll(".pageTabContent"); } function initTabs() { - mainTabsManager.setTabs(view, currentTabIndex, getTabs, getTabContainers, onBeforeTabChange, onTabChange) + mainTabsManager.setTabs(view, currentTabIndex, getTabs, getTabContainers, onBeforeTabChange, onTabChange); } function getTabController(page, index, callback) { var depends = []; + switch (index) { case 0: depends.push("controllers/shows/tvshows"); break; + case 1: break; + case 2: depends.push("controllers/shows/tvlatest"); break; + case 3: depends.push("controllers/shows/tvupcoming"); break; + case 4: depends.push("controllers/shows/tvgenres"); break; + case 5: depends.push("controllers/shows/tvstudios"); break; + case 6: depends.push("controllers/shows/episodes"); break; + case 7: - depends.push("scripts/searchtab") + depends.push("scripts/searchtab"); } - require(depends, function(controllerFactory) { + + require(depends, function (controllerFactory) { var tabContent; - 1 === index && (tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"), self.tabContent = tabContent); + + if (index === 1) { + tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"); + self.tabContent = tabContent; + } + var controller = tabControllers[index]; - controller || (tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"), controller = 1 === index ? self : 7 === index ? new controllerFactory(view, tabContent, { - collectionType: "tvshows", - parentId: params.topParentId - }) : new controllerFactory(view, params, tabContent), tabControllers[index] = controller, controller.initTab && controller.initTab()), callback(controller) - }) + + if (!controller) { + tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"); + + if (index === 1) { + controller = self; + } else if (index === 7) { + controller = new controllerFactory(view, tabContent, { + collectionType: "tvshows", + parentId: params.topParentId + }); + } else { + controller = new controllerFactory(view, params, tabContent); + } + + tabControllers[index] = controller; + + if (controller.initTab) { + controller.initTab(); + } + } + + callback(controller); + }); } function preLoadTab(page, index) { - getTabController(page, index, function(controller) { - -1 == renderedTabs.indexOf(index) && controller.preRender && controller.preRender() - }) + getTabController(page, index, function (controller) { + if (renderedTabs.indexOf(index) == -1 && controller.preRender) { + controller.preRender(); + } + }); } function loadTab(page, index) { - currentTabIndex = index, getTabController(page, index, function(controller) { - initialTabIndex = null, -1 == renderedTabs.indexOf(index) && (renderedTabs.push(index), controller.renderTab()) - }) + currentTabIndex = index; + getTabController(page, index, function (controller) { + initialTabIndex = null; + + if (renderedTabs.indexOf(index) == -1) { + renderedTabs.push(index); + controller.renderTab(); + } + }); } function onPlaybackStop(e, state) { - state.NowPlayingItem && "Video" == state.NowPlayingItem.MediaType && (renderedTabs = [], mainTabsManager.getTabsElement().triggerTabChange()) + if (state.NowPlayingItem && state.NowPlayingItem.MediaType == "Video") { + renderedTabs = []; + mainTabsManager.getTabsElement().triggerTabChange(); + } } function onWebSocketMessage(e, data) { var msg = data; - "UserDataChanged" === msg.MessageType && msg.Data.UserId == ApiClient.getCurrentUserId() && (renderedTabs = []) + + if (msg.MessageType === "UserDataChanged" && msg.Data.UserId == ApiClient.getCurrentUserId()) { + renderedTabs = []; + } } function onInputCommand(e) { switch (e.detail.command) { case "search": - e.preventDefault(), Dashboard.navigate("search.html?collectionType=tv&parentId=" + params.topParentId) + e.preventDefault(); + Dashboard.navigate("search.html?collectionType=tv&parentId=" + params.topParentId); } } - var isViewRestored, self = this, - currentTabIndex = parseInt(params.tab || getDefaultTabIndex(params.topParentId)), - initialTabIndex = currentTabIndex; - self.initTab = function() { + + var isViewRestored; + var self = this; + var currentTabIndex = parseInt(params.tab || getDefaultTabIndex(params.topParentId)); + var initialTabIndex = currentTabIndex; + + self.initTab = function () { var tabContent = self.tabContent; setScrollClasses(tabContent.querySelector("#resumableItems"), enableScrollX()); - }, self.renderTab = function() { - reload() }; - var tabControllers = [], - renderedTabs = []; - setScrollClasses(view.querySelector("#resumableItems"), enableScrollX()), view.addEventListener("viewshow", function(e) { - if (isViewRestored = e.detail.isRestored, initTabs(), !view.getAttribute("data-title")) { + + self.renderTab = function () { + reload(); + }; + + var tabControllers = []; + var renderedTabs = []; + setScrollClasses(view.querySelector("#resumableItems"), enableScrollX()); + view.addEventListener("viewshow", function (e) { + isViewRestored = e.detail.isRestored; + initTabs(); + if (!view.getAttribute("data-title")) { var parentId = params.topParentId; - parentId ? ApiClient.getItem(ApiClient.getCurrentUserId(), parentId).then(function(item) { - view.setAttribute("data-title", item.Name), libraryMenu.setTitle(item.Name) - }) : (view.setAttribute("data-title", Globalize.translate("TabShows")), libraryMenu.setTitle(Globalize.translate("TabShows"))) + + if (parentId) { + ApiClient.getItem(ApiClient.getCurrentUserId(), parentId).then(function (item) { + view.setAttribute("data-title", item.Name); + libraryMenu.setTitle(item.Name); + }); + } else { + view.setAttribute("data-title", Globalize.translate("TabShows")); + libraryMenu.setTitle(Globalize.translate("TabShows")); + } } - events.on(playbackManager, "playbackstop", onPlaybackStop), events.on(ApiClient, "message", onWebSocketMessage), inputManager.on(window, onInputCommand) - }), view.addEventListener("viewbeforehide", function(e) { - inputManager.off(window, onInputCommand), events.off(playbackManager, "playbackstop", onPlaybackStop), events.off(ApiClient, "message", onWebSocketMessage) - }), view.addEventListener("viewdestroy", function(e) { - tabControllers.forEach(function(t) { - t.destroy && t.destroy() - }) - }) - } + + events.on(playbackManager, "playbackstop", onPlaybackStop); + events.on(ApiClient, "message", onWebSocketMessage); + inputManager.on(window, onInputCommand); + }); + view.addEventListener("viewbeforehide", function (e) { + inputManager.off(window, onInputCommand); + events.off(playbackManager, "playbackstop", onPlaybackStop); + events.off(ApiClient, "message", onWebSocketMessage); + }); + view.addEventListener("viewdestroy", function (e) { + tabControllers.forEach(function (t) { + if (t.destroy) { + t.destroy(); + } + }); + }); + }; }); diff --git a/src/controllers/shows/tvshows.js b/src/controllers/shows/tvshows.js index ac832a915e..adccd98234 100644 --- a/src/controllers/shows/tvshows.js +++ b/src/controllers/shows/tvshows.js @@ -1,199 +1,284 @@ -define(["layoutManager", "loading", "events", "libraryBrowser", "imageLoader", "listView", "cardBuilder", "alphaPicker", "emby-itemscontainer"], function(layoutManager, loading, events, libraryBrowser, imageLoader, listView, cardBuilder, alphaPicker) { +define(["layoutManager", "loading", "events", "libraryBrowser", "imageLoader", "listView", "cardBuilder", "alphaPicker", "emby-itemscontainer"], function (layoutManager, loading, events, libraryBrowser, imageLoader, listView, cardBuilder, alphaPicker) { "use strict"; - return function(view, params, tabContent) { + + return function (view, params, tabContent) { function getPageData(context) { - var key = getSavedQueryKey(context), - pageData = data[key]; - return pageData || (pageData = data[key] = { - query: { - SortBy: "SortName", - SortOrder: "Ascending", - IncludeItemTypes: "Series", - Recursive: !0, - Fields: "PrimaryImageAspectRatio,BasicSyncInfo", - ImageTypeLimit: 1, - EnableImageTypes: "Primary,Backdrop,Banner,Thumb", - StartIndex: 0, - Limit: pageSize - }, - view: libraryBrowser.getSavedView(key) || "Poster" - }, pageData.query.ParentId = params.topParentId, libraryBrowser.loadSavedQueryValues(key, pageData.query)), pageData + var key = getSavedQueryKey(context); + var pageData = data[key]; + + if (!pageData) { + pageData = data[key] = { + query: { + SortBy: "SortName", + SortOrder: "Ascending", + IncludeItemTypes: "Series", + Recursive: true, + Fields: "PrimaryImageAspectRatio,BasicSyncInfo", + ImageTypeLimit: 1, + EnableImageTypes: "Primary,Backdrop,Banner,Thumb", + StartIndex: 0, + Limit: pageSize + }, + view: libraryBrowser.getSavedView(key) || "Poster" + }; + pageData.query.ParentId = params.topParentId; + libraryBrowser.loadSavedQueryValues(key, pageData.query); + } + + return pageData; } function getQuery(context) { - return getPageData(context).query + return getPageData(context).query; } function getSavedQueryKey(context) { - return context.savedQueryKey || (context.savedQueryKey = libraryBrowser.getSavedQueryKey("series")), context.savedQueryKey + if (!context.savedQueryKey) { + context.savedQueryKey = libraryBrowser.getSavedQueryKey("series"); + } + + return context.savedQueryKey; } function onViewStyleChange() { - var viewStyle = self.getCurrentViewStyle(), - itemsContainer = tabContent.querySelector(".itemsContainer"); - "List" == viewStyle ? (itemsContainer.classList.add("vertical-list"), itemsContainer.classList.remove("vertical-wrap")) : (itemsContainer.classList.remove("vertical-list"), itemsContainer.classList.add("vertical-wrap")), itemsContainer.innerHTML = "" + var viewStyle = self.getCurrentViewStyle(); + var itemsContainer = tabContent.querySelector(".itemsContainer"); + + 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.innerHTML = ""; } function reloadItems(page) { loading.show(); isLoading = true; var query = getQuery(page); - ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function(result) { + ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function (result) { function onNextPageClick() { - if (isLoading) return; + if (isLoading) { + return; + } + query.StartIndex += query.Limit; reloadItems(tabContent); } function onPreviousPageClick() { - if (isLoading) return; + if (isLoading) { + return; + } + query.StartIndex -= query.Limit; reloadItems(tabContent); } - window.scrollTo(0, 0), updateFilterControls(page); - var html, pagingHtml = libraryBrowser.getQueryPagingHtml({ - startIndex: query.StartIndex, - limit: query.Limit, - totalRecordCount: result.TotalRecordCount, - showLimit: !1, - updatePageSizeSetting: !1, - addLayoutButton: !1, - sortButton: !1, - filterButton: !1 - }), - viewStyle = self.getCurrentViewStyle(); - html = "Thumb" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "backdrop", - preferThumb: !0, - context: "tvshows", - overlayMoreButton: !0, - showTitle: !0, - centerText: !0 - }) : "ThumbCard" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "backdrop", - preferThumb: !0, - context: "tvshows", - cardLayout: !0, - showTitle: !0, - showYear: !0, - centerText: !0 - }) : "Banner" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "banner", - preferBanner: !0, - context: "tvshows" - }) : "List" == viewStyle ? listView.getListViewHtml({ - items: result.Items, - context: "tvshows", - sortBy: query.SortBy - }) : "PosterCard" == viewStyle ? cardBuilder.getCardsHtml({ - items: result.Items, - shape: "portrait", - context: "tvshows", - showTitle: !0, - showYear: !0, - centerText: !0, - cardLayout: !0 - }) : cardBuilder.getCardsHtml({ - items: result.Items, - shape: "portrait", - context: "tvshows", - centerText: !0, - lazy: !0, - overlayMoreButton: !0, - showTitle: !0, - showYear: !0 + + window.scrollTo(0, 0); + updateFilterControls(page); + var html; + var pagingHtml = libraryBrowser.getQueryPagingHtml({ + startIndex: query.StartIndex, + limit: query.Limit, + totalRecordCount: result.TotalRecordCount, + showLimit: false, + updatePageSizeSetting: false, + addLayoutButton: false, + sortButton: false, + filterButton: false }); - var i, length, elems = tabContent.querySelectorAll(".paging"); - for (i = 0, length = elems.length; i < length; i++) elems[i].innerHTML = pagingHtml; - for (elems = tabContent.querySelectorAll(".btnNextPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onNextPageClick); - for (elems = tabContent.querySelectorAll(".btnPreviousPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onPreviousPageClick); + var viewStyle = self.getCurrentViewStyle(); + if (viewStyle == "Thumb") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "backdrop", + preferThumb: true, + context: "tvshows", + overlayMoreButton: true, + showTitle: true, + centerText: true + }); + } else if (viewStyle == "ThumbCard") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "backdrop", + preferThumb: true, + context: "tvshows", + cardLayout: true, + showTitle: true, + showYear: true, + centerText: true + }); + } else if (viewStyle == "Banner") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "banner", + preferBanner: true, + context: "tvshows" + }); + } else if (viewStyle == "List") { + html = listView.getListViewHtml({ + items: result.Items, + context: "tvshows", + sortBy: query.SortBy + }); + } else if (viewStyle == "PosterCard") { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "portrait", + context: "tvshows", + showTitle: true, + showYear: true, + centerText: true, + cardLayout: true + }); + } else { + html = cardBuilder.getCardsHtml({ + items: result.Items, + shape: "portrait", + context: "tvshows", + centerText: true, + lazy: true, + overlayMoreButton: true, + showTitle: true, + showYear: true + }); + } + var i; + var length; + var elems = tabContent.querySelectorAll(".paging"); + + for (i = 0, length = elems.length; i < length; i++) { + elems[i].innerHTML = pagingHtml; + } + + elems = tabContent.querySelectorAll(".btnNextPage"); + for (i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener("click", onNextPageClick); + } + + elems = tabContent.querySelectorAll(".btnPreviousPage"); + for (i = 0, length = elems.length; i < length; i++) { + elems[i].addEventListener("click", onPreviousPageClick); + } + var itemsContainer = tabContent.querySelector(".itemsContainer"); itemsContainer.innerHTML = html; imageLoader.lazyChildren(itemsContainer); libraryBrowser.saveQueryValues(getSavedQueryKey(page), query); loading.hide(); isLoading = false; - }) + }); } function updateFilterControls(tabContent) { var query = getQuery(tabContent); - self.alphaPicker.value(query.NameStartsWithOrGreater) + self.alphaPicker.value(query.NameStartsWithOrGreater); } - var self = this, - pageSize = 100, - data = {}, - isLoading = false; - self.showFilterMenu = function() { - require(["components/filterdialog/filterdialog"], function(filterDialogFactory) { - var filterDialog = new filterDialogFactory({ - query: getQuery(tabContent), - mode: "series", - serverId: ApiClient.serverId() - }); - events.on(filterDialog, "filterchange", function() { - getQuery(tabContent).StartIndex = 0, reloadItems(tabContent) - }), filterDialog.show() - }) - }, self.getCurrentViewStyle = function() { - return getPageData(tabContent).view - }, - function(tabContent) { - var alphaPickerElement = tabContent.querySelector(".alphaPicker"); - if (alphaPickerElement.addEventListener("alphavaluechanged", function(e) { - var newValue = e.detail.value, - query = getQuery(tabContent); - query.NameStartsWithOrGreater = newValue, query.StartIndex = 0, reloadItems(tabContent) - }), self.alphaPicker = new alphaPicker({ - element: alphaPickerElement, - valueChangeEvent: "click" - }), layoutManager.desktop || layoutManager.mobile) { - tabContent.querySelector(".alphaPicker").classList.add("alphabetPicker-right"); - var itemsContainer = tabContent.querySelector(".itemsContainer"); - itemsContainer.classList.remove("padded-left-withalphapicker"), itemsContainer.classList.add("padded-right-withalphapicker") - } - tabContent.querySelector(".btnFilter").addEventListener("click", function() { - self.showFilterMenu() - }), tabContent.querySelector(".btnSort").addEventListener("click", function(e) { - libraryBrowser.showSortMenu({ - items: [{ - name: Globalize.translate("OptionNameSort"), - id: "SortName" - }, { - name: Globalize.translate("OptionImdbRating"), - id: "CommunityRating,SortName" - }, { - name: Globalize.translate("OptionDateAdded"), - id: "DateCreated,SortName" - }, { - name: Globalize.translate("OptionDatePlayed"), - id: "DatePlayed,SortName" - }, { - name: Globalize.translate("OptionParentalRating"), - id: "OfficialRating,SortName" - }, { - name: Globalize.translate("OptionReleaseDate"), - id: "PremiereDate,SortName" - }], - callback: function() { - getQuery(tabContent).StartIndex = 0, reloadItems(tabContent) - }, - query: getQuery(tabContent), - button: e.target - }) + + var self = this; + var pageSize = 100; + var data = {}; + var isLoading = false; + + self.showFilterMenu = function () { + require(["components/filterdialog/filterdialog"], function (filterDialogFactory) { + var filterDialog = new filterDialogFactory({ + query: getQuery(tabContent), + mode: "series", + serverId: ApiClient.serverId() }); - var btnSelectView = tabContent.querySelector(".btnSelectView"); - btnSelectView.addEventListener("click", function(e) { - libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), "Banner,List,Poster,PosterCard,Thumb,ThumbCard".split(",")) - }), btnSelectView.addEventListener("layoutchange", function(e) { - var viewStyle = e.detail.viewStyle; - getPageData(tabContent).view = viewStyle, libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle), getQuery(tabContent).StartIndex = 0, onViewStyleChange(), reloadItems(tabContent) - }) - }(tabContent), onViewStyleChange(), self.renderTab = function() { - reloadItems(tabContent), updateFilterControls(tabContent) - }, self.destroy = function() {} - } + events.on(filterDialog, "filterchange", function () { + getQuery(tabContent).StartIndex = 0; + reloadItems(tabContent); + }); + filterDialog.show(); + }); + }; + + self.getCurrentViewStyle = function () { + return getPageData(tabContent).view; + }; + + function initPage(tabContent) { + var alphaPickerElement = tabContent.querySelector(".alphaPicker"); + + alphaPickerElement.addEventListener("alphavaluechanged", function (e) { + var newValue = e.detail.value; + var query = getQuery(tabContent); + query.NameStartsWithOrGreater = newValue; + query.StartIndex = 0; + reloadItems(tabContent); + }); + self.alphaPicker = new alphaPicker({ + element: alphaPickerElement, + valueChangeEvent: "click" + }); + if (layoutManager.desktop || layoutManager.mobile) { + tabContent.querySelector(".alphaPicker").classList.add("alphabetPicker-right"); + var itemsContainer = tabContent.querySelector(".itemsContainer"); + itemsContainer.classList.remove("padded-left-withalphapicker"); + itemsContainer.classList.add("padded-right-withalphapicker"); + } + + tabContent.querySelector(".btnFilter").addEventListener("click", function () { + self.showFilterMenu(); + }); + tabContent.querySelector(".btnSort").addEventListener("click", function (e) { + libraryBrowser.showSortMenu({ + items: [{ + name: Globalize.translate("OptionNameSort"), + id: "SortName" + }, { + name: Globalize.translate("OptionImdbRating"), + id: "CommunityRating,SortName" + }, { + name: Globalize.translate("OptionDateAdded"), + id: "DateCreated,SortName" + }, { + name: Globalize.translate("OptionDatePlayed"), + id: "DatePlayed,SortName" + }, { + name: Globalize.translate("OptionParentalRating"), + id: "OfficialRating,SortName" + }, { + name: Globalize.translate("OptionReleaseDate"), + id: "PremiereDate,SortName" + }], + callback: function () { + getQuery(tabContent).StartIndex = 0; + reloadItems(tabContent); + }, + query: getQuery(tabContent), + button: e.target + }); + }); + var btnSelectView = tabContent.querySelector(".btnSelectView"); + btnSelectView.addEventListener("click", function (e) { + libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), "Banner,List,Poster,PosterCard,Thumb,ThumbCard".split(",")); + }); + btnSelectView.addEventListener("layoutchange", function (e) { + var viewStyle = e.detail.viewStyle; + getPageData(tabContent).view = viewStyle; + libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle); + getQuery(tabContent).StartIndex = 0; + onViewStyleChange(); + reloadItems(tabContent); + }); + } + + initPage(tabContent); + onViewStyleChange(); + + self.renderTab = function () { + reloadItems(tabContent); + updateFilterControls(tabContent); + }; + + self.destroy = function () {}; + }; }); diff --git a/src/controllers/shows/tvstudios.js b/src/controllers/shows/tvstudios.js index bfa33401f4..3c000a8e72 100644 --- a/src/controllers/shows/tvstudios.js +++ b/src/controllers/shows/tvstudios.js @@ -1,52 +1,65 @@ -define(["loading", "libraryBrowser", "cardBuilder", "apphost"], function(loading, libraryBrowser, cardBuilder, appHost) { +define(["loading", "libraryBrowser", "cardBuilder", "apphost"], function (loading, libraryBrowser, cardBuilder, appHost) { "use strict"; function getQuery(params) { - var key = getSavedQueryKey(), - pageData = data[key]; - return pageData || (pageData = data[key] = { - query: { - SortBy: "SortName", - SortOrder: "Ascending", - IncludeItemTypes: "Series", - Recursive: !0, - Fields: "DateCreated,PrimaryImageAspectRatio", - StartIndex: 0 - } - }, pageData.query.ParentId = params.topParentId), pageData.query + var key = getSavedQueryKey(); + var pageData = data[key]; + + if (!pageData) { + pageData = data[key] = { + query: { + SortBy: "SortName", + SortOrder: "Ascending", + IncludeItemTypes: "Series", + Recursive: true, + Fields: "DateCreated,PrimaryImageAspectRatio", + StartIndex: 0 + } + }; + pageData.query.ParentId = params.topParentId; + } + + return pageData.query; } function getSavedQueryKey() { - return libraryBrowser.getSavedQueryKey("studios") + return libraryBrowser.getSavedQueryKey("studios"); } function getPromise(context, params) { var query = getQuery(params); - return loading.show(), ApiClient.getStudios(ApiClient.getCurrentUserId(), query) + loading.show(); + return ApiClient.getStudios(ApiClient.getCurrentUserId(), query); } function reloadItems(context, params, promise) { - promise.then(function(result) { + promise.then(function (result) { var elem = context.querySelector("#items"); cardBuilder.buildCards(result.Items, { itemsContainer: elem, shape: "backdrop", - preferThumb: !0, - showTitle: !0, - scalable: !0, - centerText: !0, - overlayMoreButton: !0, + preferThumb: true, + showTitle: true, + scalable: true, + centerText: true, + overlayMoreButton: true, context: "tvshows" - }), loading.hide() - }) + }); + loading.hide(); + }); } + var data = {}; - return function(view, params, tabContent) { - var promise, self = this; - self.preRender = function() { - promise = getPromise(view, params) - }, self.renderTab = function() { - reloadItems(tabContent, params, promise) - } - } -}); \ No newline at end of file + return function (view, params, tabContent) { + var promise; + var self = this; + + self.preRender = function () { + promise = getPromise(view, params); + }; + + self.renderTab = function () { + reloadItems(tabContent, params, promise); + }; + }; +}); diff --git a/src/controllers/shows/tvupcoming.js b/src/controllers/shows/tvupcoming.js index 9d6a79a5ef..162e6fcb34 100644 --- a/src/controllers/shows/tvupcoming.js +++ b/src/controllers/shows/tvupcoming.js @@ -1,4 +1,4 @@ -define(["layoutManager", "loading", "datetime", "libraryBrowser", "cardBuilder", "apphost", "imageLoader", "scrollStyles", "emby-itemscontainer"], function(layoutManager, loading, datetime, libraryBrowser, cardBuilder, appHost, imageLoader) { +define(["layoutManager", "loading", "datetime", "libraryBrowser", "cardBuilder", "apphost", "imageLoader", "scrollStyles", "emby-itemscontainer"], function (layoutManager, loading, datetime, libraryBrowser, cardBuilder, appHost, imageLoader) { "use strict"; function getUpcomingPromise(context, params) { @@ -9,82 +9,129 @@ define(["layoutManager", "loading", "datetime", "libraryBrowser", "cardBuilder", UserId: ApiClient.getCurrentUserId(), ImageTypeLimit: 1, EnableImageTypes: "Primary,Backdrop,Banner,Thumb", - EnableTotalRecordCount: !1 + EnableTotalRecordCount: false }; - return query.ParentId = params.topParentId, ApiClient.getJSON(ApiClient.getUrl("Shows/Upcoming", query)) + query.ParentId = params.topParentId; + return ApiClient.getJSON(ApiClient.getUrl("Shows/Upcoming", query)); } function loadUpcoming(context, params, promise) { - promise.then(function(result) { + promise.then(function (result) { var items = result.Items; - items.length ? context.querySelector(".noItemsMessage").style.display = "none" : context.querySelector(".noItemsMessage").style.display = "block", renderUpcoming(context.querySelector("#upcomingItems"), items), loading.hide() - }) + + if (items.length) { + context.querySelector(".noItemsMessage").style.display = "none"; + } else { + context.querySelector(".noItemsMessage").style.display = "block"; + } + + renderUpcoming(context.querySelector("#upcomingItems"), items); + loading.hide(); + }); } function enableScrollX() { - return !layoutManager.desktop + return !layoutManager.desktop; } function getThumbShape() { - return enableScrollX() ? "overflowBackdrop" : "backdrop" + return enableScrollX() ? "overflowBackdrop" : "backdrop"; } function renderUpcoming(elem, items) { - var i, length, groups = [], - currentGroupName = "", - currentGroup = []; + var i; + var length; + var groups = []; + var currentGroupName = ""; + var currentGroup = []; + for (i = 0, length = items.length; i < length; i++) { - var item = items[i], - dateText = ""; - if (item.PremiereDate) try { - var premiereDate = datetime.parseISO8601Date(item.PremiereDate, !0); - dateText = datetime.isRelativeDay(premiereDate, -1) ? Globalize.translate("Yesterday") : datetime.toLocaleDateString(premiereDate, { - weekday: "long", - month: "short", - day: "numeric" - }) - } catch (err) {} - dateText != currentGroupName ? (currentGroup.length && groups.push({ - name: currentGroupName, - items: currentGroup - }), currentGroupName = dateText, currentGroup = [item]) : currentGroup.push(item) + var item = items[i]; + var dateText = ""; + + if (item.PremiereDate) { + try { + var premiereDate = datetime.parseISO8601Date(item.PremiereDate, true); + dateText = datetime.isRelativeDay(premiereDate, -1) ? Globalize.translate("Yesterday") : datetime.toLocaleDateString(premiereDate, { + weekday: "long", + month: "short", + day: "numeric" + }); + } catch (err) {} + } + + if (dateText != currentGroupName) { + if (currentGroup.length) { + groups.push({ + name: currentGroupName, + items: currentGroup + }); + } + + currentGroupName = dateText; + currentGroup = [item]; + } else { + currentGroup.push(item); + } } + var html = ""; + for (i = 0, length = groups.length; i < length; i++) { var group = groups[i]; - html += '
', html += '

' + group.name + "

"; - var allowBottomPadding = !0; + html += '
'; + html += '

' + group.name + "

"; + var allowBottomPadding = true; + if (enableScrollX()) { - allowBottomPadding = !1; + allowBottomPadding = false; var scrollXClass = "scrollX hiddenScrollX"; - layoutManager.tv && (scrollXClass += " smoothScrollX"), html += '
' - } else html += '
'; + + if (layoutManager.tv) { + scrollXClass += " smoothScrollX"; + } + + html += '
'; + } else { + html += '
'; + } + var supportsImageAnalysis = appHost.supports("imageanalysis"); - supportsImageAnalysis = !1, html += cardBuilder.getCardsHtml({ + supportsImageAnalysis = false; + html += cardBuilder.getCardsHtml({ items: group.items, - showLocationTypeIndicator: !1, + showLocationTypeIndicator: false, shape: getThumbShape(), - showTitle: !0, - preferThumb: !0, - lazy: !0, - showDetailsMenu: !0, + showTitle: true, + preferThumb: true, + lazy: true, + showDetailsMenu: true, centerText: !supportsImageAnalysis, - showParentTitle: !0, - overlayText: !1, + showParentTitle: true, + overlayText: false, allowBottomPadding: allowBottomPadding, cardLayout: supportsImageAnalysis, - overlayMoreButton: !0, - missingIndicator: !1 - }), html += "
", html += "
" + overlayMoreButton: true, + missingIndicator: false + }); + html += "
"; + html += "
"; } - elem.innerHTML = html, imageLoader.lazyChildren(elem) + + elem.innerHTML = html; + imageLoader.lazyChildren(elem); } - return function(view, params, tabContent) { - var upcomingPromise, self = this; - self.preRender = function() { - upcomingPromise = getUpcomingPromise(view, params) - }, self.renderTab = function() { - loadUpcoming(tabContent, params, upcomingPromise) - } - } -}); \ No newline at end of file + + return function (view, params, tabContent) { + var upcomingPromise; + var self = this; + + self.preRender = function () { + upcomingPromise = getUpcomingPromise(view, params); + }; + + self.renderTab = function () { + loadUpcoming(tabContent, params, upcomingPromise); + }; + }; +}); diff --git a/src/controllers/streamingsettings.js b/src/controllers/streamingsettings.js index 6f19a68422..6c85034458 100644 --- a/src/controllers/streamingsettings.js +++ b/src/controllers/streamingsettings.js @@ -1,16 +1,19 @@ -define(["jQuery", "libraryMenu", "loading"], function($, libraryMenu, loading) { +define(["jQuery", "libraryMenu", "loading"], function ($, libraryMenu, loading) { "use strict"; function loadPage(page, config) { - $("#txtRemoteClientBitrateLimit", page).val(config.RemoteClientBitrateLimit / 1e6 || ""), loading.hide() + $("#txtRemoteClientBitrateLimit", page).val(config.RemoteClientBitrateLimit / 1e6 || ""); + loading.hide(); } function onSubmit() { loading.show(); var form = this; - return ApiClient.getServerConfiguration().then(function(config) { - config.RemoteClientBitrateLimit = parseInt(1e6 * parseFloat($("#txtRemoteClientBitrateLimit", form).val() || "0")), ApiClient.updateServerConfiguration(config).then(Dashboard.processServerConfigurationUpdateResult) - }), !1 + ApiClient.getServerConfiguration().then(function (config) { + config.RemoteClientBitrateLimit = parseInt(1e6 * parseFloat($("#txtRemoteClientBitrateLimit", form).val() || "0")); + ApiClient.updateServerConfiguration(config).then(Dashboard.processServerConfigurationUpdateResult); + }); + return false; } function getTabs() { @@ -23,30 +26,35 @@ define(["jQuery", "libraryMenu", "loading"], function($, libraryMenu, loading) { }, { href: "streamingsettings.html", name: Globalize.translate("TabStreaming") - }] + }]; } - $(document).on("pageinit", "#streamingSettingsPage", function() { + $(document).on("pageinit", "#streamingSettingsPage", function () { var page = this; - $("#btnSelectTranscodingTempPath", page).on("click.selectDirectory", function() { - require(["directorybrowser"], function(directoryBrowser) { - var picker = new directoryBrowser; + $("#btnSelectTranscodingTempPath", page).on("click.selectDirectory", function () { + require(["directorybrowser"], function (directoryBrowser) { + var picker = new directoryBrowser(); picker.show({ - callback: function(path) { - path && $("#txtTranscodingTempPath", page).val(path), picker.close() + callback: function (path) { + if (path) { + $("#txtTranscodingTempPath", page).val(path); + } + + picker.close(); }, - validateWriteable: !0, + validateWriteable: true, header: Globalize.translate("HeaderSelectTranscodingPath"), instruction: Globalize.translate("HeaderSelectTranscodingPathHelp") - }) - }) - }), $(".streamingSettingsForm").off("submit", onSubmit).on("submit", onSubmit) - }).on("pageshow", "#streamingSettingsPage", function() { + }); + }); + }); + $(".streamingSettingsForm").off("submit", onSubmit).on("submit", onSubmit); + }).on("pageshow", "#streamingSettingsPage", function () { loading.show(); libraryMenu.setTabs("playback", 2, getTabs); var page = this; - ApiClient.getServerConfiguration().then(function(config) { - loadPage(page, config) - }) - }) -}); \ No newline at end of file + ApiClient.getServerConfiguration().then(function (config) { + loadPage(page, config); + }); + }); +}); diff --git a/src/controllers/user/display.js b/src/controllers/user/display.js index 4b4440f96a..f91e874a89 100644 --- a/src/controllers/user/display.js +++ b/src/controllers/user/display.js @@ -1,28 +1,49 @@ -define(["displaySettings", "userSettingsBuilder", "userSettings"], function(DisplaySettings, userSettingsBuilder, currentUserSettings) { +define(["displaySettings", "userSettingsBuilder", "userSettings"], function (DisplaySettings, userSettingsBuilder, currentUserSettings) { "use strict"; - return function(view, params) { + + return function (view, params) { function onBeforeUnload(e) { - hasChanges && (e.returnValue = "You currently have unsaved changes. Are you sure you wish to leave?") + if (hasChanges) { + e.returnValue = "You currently have unsaved changes. Are you sure you wish to leave?"; + } } - var settingsInstance, hasChanges, userId = params.userId || ApiClient.getCurrentUserId(), - userSettings = userId === ApiClient.getCurrentUserId() ? currentUserSettings : new userSettingsBuilder; - view.addEventListener("viewshow", function() { - window.addEventListener("beforeunload", onBeforeUnload), settingsInstance ? settingsInstance.loadData() : settingsInstance = new DisplaySettings({ - serverId: ApiClient.serverId(), - userId: userId, - element: view.querySelector(".settingsContainer"), - userSettings: userSettings, - enableSaveButton: !1, - enableSaveConfirmation: !1 - }) - }), view.addEventListener("change", function() { - hasChanges = !0 - }), view.addEventListener("viewbeforehide", function() { - window.removeEventListener("beforeunload", onBeforeUnload), hasChanges = !1, settingsInstance && settingsInstance.submit() - }), view.addEventListener("viewdestroy", function() { - settingsInstance && (settingsInstance.destroy(), settingsInstance = null) - }), view.addEventListener("viewdestroy", function() { - settingsInstance && (settingsInstance.destroy(), settingsInstance = null) - }) - } -}); \ No newline at end of file + + var settingsInstance; + var hasChanges; + var userId = params.userId || ApiClient.getCurrentUserId(); + var userSettings = userId === ApiClient.getCurrentUserId() ? currentUserSettings : new userSettingsBuilder(); + view.addEventListener("viewshow", function () { + window.addEventListener("beforeunload", onBeforeUnload); + + if (settingsInstance) { + settingsInstance.loadData(); + } else { + settingsInstance = new DisplaySettings({ + serverId: ApiClient.serverId(), + userId: userId, + element: view.querySelector(".settingsContainer"), + userSettings: userSettings, + enableSaveButton: false, + enableSaveConfirmation: false + }); + } + }); + view.addEventListener("change", function () { + hasChanges = true; + }); + view.addEventListener("viewbeforehide", function () { + window.removeEventListener("beforeunload", onBeforeUnload); + hasChanges = false; + + if (settingsInstance) { + settingsInstance.submit(); + } + }); + view.addEventListener("viewdestroy", function () { + if (settingsInstance) { + settingsInstance.destroy(); + settingsInstance = null; + } + }); + }; +}); diff --git a/src/controllers/user/home.js b/src/controllers/user/home.js index a7147ddda3..5794d58723 100644 --- a/src/controllers/user/home.js +++ b/src/controllers/user/home.js @@ -1,26 +1,48 @@ -define(["homescreenSettings", "userSettingsBuilder", "dom", "globalize", "loading", "userSettings", "listViewStyle"], function(HomescreenSettings, userSettingsBuilder, dom, globalize, loading, currentUserSettings) { +define(["homescreenSettings", "userSettingsBuilder", "dom", "globalize", "loading", "userSettings", "listViewStyle"], function (HomescreenSettings, userSettingsBuilder, dom, globalize, loading, currentUserSettings) { "use strict"; - return function(view, params) { + + return function (view, params) { function onBeforeUnload(e) { - hasChanges && (e.returnValue = "You currently have unsaved changes. Are you sure you wish to leave?") + if (hasChanges) { + e.returnValue = "You currently have unsaved changes. Are you sure you wish to leave?"; + } } - var homescreenSettingsInstance, hasChanges, userId = params.userId || ApiClient.getCurrentUserId(), - userSettings = userId === ApiClient.getCurrentUserId() ? currentUserSettings : new userSettingsBuilder; - view.addEventListener("viewshow", function() { - window.addEventListener("beforeunload", onBeforeUnload), homescreenSettingsInstance ? homescreenSettingsInstance.loadData() : homescreenSettingsInstance = new HomescreenSettings({ - serverId: ApiClient.serverId(), - userId: userId, - element: view.querySelector(".homeScreenSettingsContainer"), - userSettings: userSettings, - enableSaveButton: !1, - enableSaveConfirmation: !1 - }) - }), view.addEventListener("change", function() { - hasChanges = !0 - }), view.addEventListener("viewbeforehide", function() { - hasChanges = !1, homescreenSettingsInstance && homescreenSettingsInstance.submit() - }), view.addEventListener("viewdestroy", function() { - homescreenSettingsInstance && (homescreenSettingsInstance.destroy(), homescreenSettingsInstance = null) - }) - } -}); \ No newline at end of file + + var homescreenSettingsInstance; + var hasChanges; + var userId = params.userId || ApiClient.getCurrentUserId(); + var userSettings = userId === ApiClient.getCurrentUserId() ? currentUserSettings : new userSettingsBuilder(); + view.addEventListener("viewshow", function () { + window.addEventListener("beforeunload", onBeforeUnload); + + if (homescreenSettingsInstance) { + homescreenSettingsInstance.loadData(); + } else { + homescreenSettingsInstance = new HomescreenSettings({ + serverId: ApiClient.serverId(), + userId: userId, + element: view.querySelector(".homeScreenSettingsContainer"), + userSettings: userSettings, + enableSaveButton: false, + enableSaveConfirmation: false + }); + } + }); + view.addEventListener("change", function () { + hasChanges = true; + }); + view.addEventListener("viewbeforehide", function () { + hasChanges = false; + + if (homescreenSettingsInstance) { + homescreenSettingsInstance.submit(); + } + }); + view.addEventListener("viewdestroy", function () { + if (homescreenSettingsInstance) { + homescreenSettingsInstance.destroy(); + homescreenSettingsInstance = null; + } + }); + }; +}); diff --git a/src/controllers/user/menu.js b/src/controllers/user/menu.js index 6bac0011d2..d9fa2ab998 100644 --- a/src/controllers/user/menu.js +++ b/src/controllers/user/menu.js @@ -18,7 +18,7 @@ define(["apphost", "connectionManager", "listViewStyle", "emby-button"], functio page.querySelector(".lnkSubtitlePreferences").setAttribute("href", "mypreferencessubtitles.html?userId=" + userId); if (appHost.supports("multiserver")) { - page.querySelector(".selectServer").classList.remove("hide") + page.querySelector(".selectServer").classList.remove("hide"); } else { page.querySelector(".selectServer").classList.add("hide"); } @@ -35,6 +35,6 @@ define(["apphost", "connectionManager", "listViewStyle", "emby-button"], functio page.querySelector(".adminSection").classList.add("hide"); } }); - }) - } + }); + }; }); diff --git a/src/controllers/user/playback.js b/src/controllers/user/playback.js index 856470948a..f2463ad8df 100644 --- a/src/controllers/user/playback.js +++ b/src/controllers/user/playback.js @@ -1,26 +1,48 @@ -define(["playbackSettings", "userSettingsBuilder", "dom", "globalize", "loading", "userSettings", "listViewStyle"], function(PlaybackSettings, userSettingsBuilder, dom, globalize, loading, currentUserSettings) { +define(["playbackSettings", "userSettingsBuilder", "dom", "globalize", "loading", "userSettings", "listViewStyle"], function (PlaybackSettings, userSettingsBuilder, dom, globalize, loading, currentUserSettings) { "use strict"; - return function(view, params) { + + return function (view, params) { function onBeforeUnload(e) { - hasChanges && (e.returnValue = "You currently have unsaved changes. Are you sure you wish to leave?") + if (hasChanges) { + e.returnValue = "You currently have unsaved changes. Are you sure you wish to leave?"; + } } - var settingsInstance, hasChanges, userId = params.userId || ApiClient.getCurrentUserId(), - userSettings = userId === ApiClient.getCurrentUserId() ? currentUserSettings : new userSettingsBuilder; - view.addEventListener("viewshow", function() { - window.addEventListener("beforeunload", onBeforeUnload), settingsInstance ? settingsInstance.loadData() : settingsInstance = new PlaybackSettings({ - serverId: ApiClient.serverId(), - userId: userId, - element: view.querySelector(".settingsContainer"), - userSettings: userSettings, - enableSaveButton: !1, - enableSaveConfirmation: !1 - }) - }), view.addEventListener("change", function() { - hasChanges = !0 - }), view.addEventListener("viewbeforehide", function() { - hasChanges = !1, settingsInstance && settingsInstance.submit() - }), view.addEventListener("viewdestroy", function() { - settingsInstance && (settingsInstance.destroy(), settingsInstance = null) - }) - } -}); \ No newline at end of file + + var settingsInstance; + var hasChanges; + var userId = params.userId || ApiClient.getCurrentUserId(); + var userSettings = userId === ApiClient.getCurrentUserId() ? currentUserSettings : new userSettingsBuilder(); + view.addEventListener("viewshow", function () { + window.addEventListener("beforeunload", onBeforeUnload); + + if (settingsInstance) { + settingsInstance.loadData(); + } else { + settingsInstance = new PlaybackSettings({ + serverId: ApiClient.serverId(), + userId: userId, + element: view.querySelector(".settingsContainer"), + userSettings: userSettings, + enableSaveButton: false, + enableSaveConfirmation: false + }); + } + }); + view.addEventListener("change", function () { + hasChanges = true; + }); + view.addEventListener("viewbeforehide", function () { + hasChanges = false; + + if (settingsInstance) { + settingsInstance.submit(); + } + }); + view.addEventListener("viewdestroy", function () { + if (settingsInstance) { + settingsInstance.destroy(); + settingsInstance = null; + } + }); + }; +}); diff --git a/src/controllers/user/subtitles.js b/src/controllers/user/subtitles.js index 81d949e1a9..205265efcd 100644 --- a/src/controllers/user/subtitles.js +++ b/src/controllers/user/subtitles.js @@ -1,26 +1,48 @@ -define(["subtitleSettings", "userSettingsBuilder", "userSettings"], function(SubtitleSettings, userSettingsBuilder, currentUserSettings) { +define(["subtitleSettings", "userSettingsBuilder", "userSettings"], function (SubtitleSettings, userSettingsBuilder, currentUserSettings) { "use strict"; - return function(view, params) { + + return function (view, params) { function onBeforeUnload(e) { - hasChanges && (e.returnValue = "You currently have unsaved changes. Are you sure you wish to leave?") + if (hasChanges) { + e.returnValue = "You currently have unsaved changes. Are you sure you wish to leave?"; + } } - var subtitleSettingsInstance, hasChanges, userId = params.userId || ApiClient.getCurrentUserId(), - userSettings = userId === ApiClient.getCurrentUserId() ? currentUserSettings : new userSettingsBuilder; - view.addEventListener("viewshow", function() { - window.addEventListener("beforeunload", onBeforeUnload), subtitleSettingsInstance ? subtitleSettingsInstance.loadData() : subtitleSettingsInstance = new SubtitleSettings({ - serverId: ApiClient.serverId(), - userId: userId, - element: view.querySelector(".settingsContainer"), - userSettings: userSettings, - enableSaveButton: !1, - enableSaveConfirmation: !1 - }) - }), view.addEventListener("change", function() { - hasChanges = !0 - }), view.addEventListener("viewbeforehide", function() { - hasChanges = !1, subtitleSettingsInstance && subtitleSettingsInstance.submit() - }), view.addEventListener("viewdestroy", function() { - subtitleSettingsInstance && (subtitleSettingsInstance.destroy(), subtitleSettingsInstance = null) - }) - } -}); \ No newline at end of file + + var subtitleSettingsInstance; + var hasChanges; + var userId = params.userId || ApiClient.getCurrentUserId(); + var userSettings = userId === ApiClient.getCurrentUserId() ? currentUserSettings : new userSettingsBuilder(); + view.addEventListener("viewshow", function () { + window.addEventListener("beforeunload", onBeforeUnload); + + if (subtitleSettingsInstance) { + subtitleSettingsInstance.loadData(); + } else { + subtitleSettingsInstance = new SubtitleSettings({ + serverId: ApiClient.serverId(), + userId: userId, + element: view.querySelector(".settingsContainer"), + userSettings: userSettings, + enableSaveButton: false, + enableSaveConfirmation: false + }); + } + }); + view.addEventListener("change", function () { + hasChanges = true; + }); + view.addEventListener("viewbeforehide", function () { + hasChanges = false; + + if (subtitleSettingsInstance) { + subtitleSettingsInstance.submit(); + } + }); + view.addEventListener("viewdestroy", function () { + if (subtitleSettingsInstance) { + subtitleSettingsInstance.destroy(); + subtitleSettingsInstance = null; + } + }); + }; +}); diff --git a/src/controllers/useredit.js b/src/controllers/useredit.js index 0709e8dae9..fb6a3f94cd 100644 --- a/src/controllers/useredit.js +++ b/src/controllers/useredit.js @@ -1,53 +1,84 @@ -define(["jQuery", "loading", "libraryMenu", "fnchecked"], function($, loading, libraryMenu) { +define(["jQuery", "loading", "libraryMenu", "fnchecked"], function ($, loading, libraryMenu) { "use strict"; function loadDeleteFolders(page, user, mediaFolders) { ApiClient.getJSON(ApiClient.getUrl("Channels", { - SupportsMediaDeletion: !0 - })).then(function(channelsResult) { - var i, length, folder, isChecked, checkedAttribute, html = ""; - for (i = 0, length = mediaFolders.length; i < length; i++) folder = mediaFolders[i], isChecked = user.Policy.EnableContentDeletion || -1 != user.Policy.EnableContentDeletionFromFolders.indexOf(folder.Id), checkedAttribute = isChecked ? ' checked="checked"' : "", html += '"; - for (i = 0, length = channelsResult.Items.length; i < length; i++) folder = channelsResult.Items[i], isChecked = user.Policy.EnableContentDeletion || -1 != user.Policy.EnableContentDeletionFromFolders.indexOf(folder.Id), checkedAttribute = isChecked ? ' checked="checked"' : "", html += '"; - $(".deleteAccess", page).html(html).trigger("create"), $("#chkEnableDeleteAllFolders", page).checked(user.Policy.EnableContentDeletion).trigger("change") - }) + SupportsMediaDeletion: true + })).then(function (channelsResult) { + var i; + var length; + var folder; + var isChecked; + var checkedAttribute; + var html = ""; + + for (i = 0, length = mediaFolders.length; i < length; i++) { + folder = mediaFolders[i]; + isChecked = user.Policy.EnableContentDeletion || -1 != user.Policy.EnableContentDeletionFromFolders.indexOf(folder.Id); + checkedAttribute = isChecked ? ' checked="checked"' : ""; + html += '"; + } + + for (i = 0, length = channelsResult.Items.length; i < length; i++) { + folder = channelsResult.Items[i]; + isChecked = user.Policy.EnableContentDeletion || -1 != user.Policy.EnableContentDeletionFromFolders.indexOf(folder.Id); + checkedAttribute = isChecked ? ' checked="checked"' : ""; + html += '"; + } + + $(".deleteAccess", page).html(html).trigger("create"); + $("#chkEnableDeleteAllFolders", page).checked(user.Policy.EnableContentDeletion).trigger("change"); + }); } function loadAuthProviders(page, user, providers) { - providers.length > 1 ? page.querySelector(".fldSelectLoginProvider").classList.remove("hide") : page.querySelector(".fldSelectLoginProvider").classList.add("hide"); + if (providers.length > 1) { + page.querySelector(".fldSelectLoginProvider").classList.remove("hide"); + } else { + page.querySelector(".fldSelectLoginProvider").classList.add("hide"); + } + var currentProviderId = user.Policy.AuthenticationProviderId; - page.querySelector(".selectLoginProvider").innerHTML = providers.map(function(provider) { + page.querySelector(".selectLoginProvider").innerHTML = providers.map(function (provider) { var selected = provider.Id === currentProviderId || providers.length < 2 ? " selected" : ""; - return '" - }) + return '"; + }); } function loadPasswordResetProviders(page, user, providers) { - providers.length > 1 ? page.querySelector(".fldSelectPasswordResetProvider").classList.remove("hide") : page.querySelector(".fldSelectPasswordResetProvider").classList.add("hide"); + if (providers.length > 1) { + page.querySelector(".fldSelectPasswordResetProvider").classList.remove("hide"); + } else { + page.querySelector(".fldSelectPasswordResetProvider").classList.add("hide"); + } + var currentProviderId = user.Policy.PasswordResetProviderId; - page.querySelector(".selectPasswordResetProvider").innerHTML = providers.map(function(provider) { - var selected = (provider.Id === currentProviderId || providers.length < 2) ? " selected" : ""; - return '" - }) + page.querySelector(".selectPasswordResetProvider").innerHTML = providers.map(function (provider) { + var selected = provider.Id === currentProviderId || providers.length < 2 ? " selected" : ""; + return '"; + }); } function loadUser(page, user) { currentUser = user; - ApiClient.getJSON(ApiClient.getUrl("Auth/Providers")).then(function(providers) { - loadAuthProviders(page, user, providers) + ApiClient.getJSON(ApiClient.getUrl("Auth/Providers")).then(function (providers) { + loadAuthProviders(page, user, providers); }); - ApiClient.getJSON(ApiClient.getUrl("Auth/PasswordResetProviders")).then(function(providers) { - loadPasswordResetProviders(page, user, providers) + ApiClient.getJSON(ApiClient.getUrl("Auth/PasswordResetProviders")).then(function (providers) { + loadPasswordResetProviders(page, user, providers); }); ApiClient.getJSON(ApiClient.getUrl("Library/MediaFolders", { - IsHidden: false - })).then(function(folders) { - loadDeleteFolders(page, user, folders.Items) + IsHidden: false + })).then(function (folders) { + loadDeleteFolders(page, user, folders.Items); }); + if (user.Policy.IsDisabled) { $(".disabledUserBanner", page).show(); } else { $(".disabledUserBanner", page).hide(); } + $("#txtUserName", page).prop("disabled", "").removeAttr("disabled"); $("#fldConnectInfo", page).show(); $(".lnkEditUserPreferences", page).attr("href", "mypreferencesmenu.html?userId=" + user.Id); @@ -78,7 +109,8 @@ define(["jQuery", "loading", "libraryMenu", "fnchecked"], function($, loading, l function onSaveComplete(page, user) { Dashboard.navigate("userprofiles.html"); loading.hide(); - require(["toast"], function(toast) { + + require(["toast"], function (toast) { toast(Globalize.translate("SettingsSaved")); }); } @@ -106,45 +138,59 @@ define(["jQuery", "loading", "libraryMenu", "fnchecked"], function($, loading, l user.Policy.AuthenticationProviderId = page.querySelector(".selectLoginProvider").value; user.Policy.PasswordResetProviderId = page.querySelector(".selectPasswordResetProvider").value; user.Policy.EnableContentDeletion = $("#chkEnableDeleteAllFolders", page).checked(); - user.Policy.EnableContentDeletionFromFolders = user.Policy.EnableContentDeletion ? [] : $(".chkFolder", page).get().filter(function(c) { - return c.checked - }).map(function(c) { - return c.getAttribute("data-id") + user.Policy.EnableContentDeletionFromFolders = user.Policy.EnableContentDeletion ? [] : $(".chkFolder", page).get().filter(function (c) { + return c.checked; + }).map(function (c) { + return c.getAttribute("data-id"); + }); + ApiClient.updateUser(user).then(function () { + ApiClient.updateUserPolicy(user.Id, user.Policy).then(function () { + onSaveComplete(page, user); + }); }); - ApiClient.updateUser(user).then(function() { - ApiClient.updateUserPolicy(user.Id, user.Policy).then(function() { - onSaveComplete(page, user) - }) - }) } function onSubmit() { var page = $(this).parents(".page")[0]; - return loading.show(), getUser().then(function(result) { - saveUser(result, page) - }), !1 + loading.show(); + getUser().then(function (result) { + saveUser(result, page); + }); + return false; } function getUser() { var userId = getParameterByName("userId"); - return ApiClient.getUser(userId) + return ApiClient.getUser(userId); } function loadData(page) { - loading.show(), getUser().then(function(user) { - loadUser(page, user) - }) + loading.show(); + getUser().then(function (user) { + loadUser(page, user); + }); } + var currentUser; - $(document).on("pageinit", "#editUserPage", function() { - $(".editUserProfileForm").off("submit", onSubmit).on("submit", onSubmit), this.querySelector(".sharingHelp").innerHTML = Globalize.translate("OptionAllowLinkSharingHelp", 30); + $(document).on("pageinit", "#editUserPage", function () { + $(".editUserProfileForm").off("submit", onSubmit).on("submit", onSubmit); + this.querySelector(".sharingHelp").innerHTML = Globalize.translate("OptionAllowLinkSharingHelp", 30); var page = this; - $("#chkEnableDeleteAllFolders", this).on("change", function() { - this.checked ? $(".deleteAccess", page).hide() : $(".deleteAccess", page).show() - }), ApiClient.getServerConfiguration().then(function(config) { - config.EnableRemoteAccess ? page.querySelector(".fldRemoteAccess").classList.remove("hide") : page.querySelector(".fldRemoteAccess").classList.add("hide") - }) - }).on("pagebeforeshow", "#editUserPage", function() { - loadData(this) - }) + $("#chkEnableDeleteAllFolders", this).on("change", function () { + if (this.checked) { + $(".deleteAccess", page).hide(); + } else { + $(".deleteAccess", page).show(); + } + }); + ApiClient.getServerConfiguration().then(function (config) { + if (config.EnableRemoteAccess) { + page.querySelector(".fldRemoteAccess").classList.remove("hide"); + } else { + page.querySelector(".fldRemoteAccess").classList.add("hide"); + } + }); + }).on("pagebeforeshow", "#editUserPage", function () { + loadData(this); + }); }); diff --git a/src/controllers/userlibraryaccess.js b/src/controllers/userlibraryaccess.js index 8352e90c3e..38418f5190 100644 --- a/src/controllers/userlibraryaccess.js +++ b/src/controllers/userlibraryaccess.js @@ -1,112 +1,178 @@ -define(["jQuery", "loading", "libraryMenu", "fnchecked"], function($, loading, libraryMenu) { +define(["jQuery", "loading", "libraryMenu", "fnchecked"], function ($, loading, libraryMenu) { "use strict"; function triggerChange(select) { var evt = document.createEvent("HTMLEvents"); - evt.initEvent("change", !1, !0), select.dispatchEvent(evt) + evt.initEvent("change", false, true); + select.dispatchEvent(evt); } function loadMediaFolders(page, user, mediaFolders) { var html = ""; - html += '

' + Globalize.translate("HeaderLibraries") + "

", html += '
'; + html += '

' + Globalize.translate("HeaderLibraries") + "

"; + html += '
'; + for (var i = 0, length = mediaFolders.length; i < length; i++) { - var folder = mediaFolders[i], - isChecked = user.Policy.EnableAllFolders || -1 != user.Policy.EnabledFolders.indexOf(folder.Id), - checkedAttribute = isChecked ? ' checked="checked"' : ""; - html += '" + var folder = mediaFolders[i]; + var isChecked = user.Policy.EnableAllFolders || -1 != user.Policy.EnabledFolders.indexOf(folder.Id); + var checkedAttribute = isChecked ? ' checked="checked"' : ""; + html += '"; } - html += "
", page.querySelector(".folderAccess").innerHTML = html; + + html += "
"; + page.querySelector(".folderAccess").innerHTML = html; var chkEnableAllFolders = page.querySelector("#chkEnableAllFolders"); - chkEnableAllFolders.checked = user.Policy.EnableAllFolders, triggerChange(chkEnableAllFolders) + chkEnableAllFolders.checked = user.Policy.EnableAllFolders; + triggerChange(chkEnableAllFolders); } function loadChannels(page, user, channels) { var html = ""; - html += '

' + Globalize.translate("HeaderChannels") + "

", html += '
'; + html += '

' + Globalize.translate("HeaderChannels") + "

"; + html += '
'; + for (var i = 0, length = channels.length; i < length; i++) { - var folder = channels[i], - isChecked = user.Policy.EnableAllChannels || -1 != user.Policy.EnabledChannels.indexOf(folder.Id), - checkedAttribute = isChecked ? ' checked="checked"' : ""; - html += '" + var folder = channels[i]; + var isChecked = user.Policy.EnableAllChannels || -1 != user.Policy.EnabledChannels.indexOf(folder.Id); + var checkedAttribute = isChecked ? ' checked="checked"' : ""; + html += '"; } - html += "
", $(".channelAccess", page).show().html(html), channels.length ? $(".channelAccessContainer", page).show() : $(".channelAccessContainer", page).hide(), $("#chkEnableAllChannels", page).checked(user.Policy.EnableAllChannels).trigger("change") + + html += "
"; + $(".channelAccess", page).show().html(html); + + if (channels.length) { + $(".channelAccessContainer", page).show(); + } else { + $(".channelAccessContainer", page).hide(); + } + + $("#chkEnableAllChannels", page).checked(user.Policy.EnableAllChannels).trigger("change"); } function loadDevices(page, user, devices) { var html = ""; - html += '

' + Globalize.translate("HeaderDevices") + "

", html += '
'; + html += '

' + Globalize.translate("HeaderDevices") + "

"; + html += '
'; + for (var i = 0, length = devices.length; i < length; i++) { - var device = devices[i], - checkedAttribute = user.Policy.EnableAllDevices || -1 != user.Policy.EnabledDevices.indexOf(device.Id) ? ' checked="checked"' : ""; - html += '" + var device = devices[i]; + var checkedAttribute = user.Policy.EnableAllDevices || -1 != user.Policy.EnabledDevices.indexOf(device.Id) ? ' checked="checked"' : ""; + html += '"; + } + + html += "
"; + $(".deviceAccess", page).show().html(html); + $("#chkEnableAllDevices", page).checked(user.Policy.EnableAllDevices).trigger("change"); + + if (user.Policy.IsAdministrator) { + page.querySelector(".deviceAccessContainer").classList.add("hide"); + } else { + page.querySelector(".deviceAccessContainer").classList.remove("hide"); } - html += "
", $(".deviceAccess", page).show().html(html), $("#chkEnableAllDevices", page).checked(user.Policy.EnableAllDevices).trigger("change"), user.Policy.IsAdministrator ? page.querySelector(".deviceAccessContainer").classList.add("hide") : page.querySelector(".deviceAccessContainer").classList.remove("hide") } function loadUser(page, user, loggedInUser, mediaFolders, channels, devices) { - page.querySelector(".username").innerHTML = user.Name, libraryMenu.setTitle(user.Name), loadChannels(page, user, channels), loadMediaFolders(page, user, mediaFolders), loadDevices(page, user, devices), loading.hide() + page.querySelector(".username").innerHTML = user.Name; + libraryMenu.setTitle(user.Name); + loadChannels(page, user, channels); + loadMediaFolders(page, user, mediaFolders); + loadDevices(page, user, devices); + loading.hide(); } function onSaveComplete(page) { - loading.hide(), require(["toast"], function(toast) { - toast(Globalize.translate("SettingsSaved")) - }) + loading.hide(); + + require(["toast"], function (toast) { + toast(Globalize.translate("SettingsSaved")); + }); } function saveUser(user, page) { - user.Policy.EnableAllFolders = $("#chkEnableAllFolders", page).checked(), user.Policy.EnabledFolders = user.Policy.EnableAllFolders ? [] : $(".chkFolder", page).get().filter(function(c) { - return c.checked - }).map(function(c) { - return c.getAttribute("data-id") - }), user.Policy.EnableAllChannels = $("#chkEnableAllChannels", page).checked(), user.Policy.EnabledChannels = user.Policy.EnableAllChannels ? [] : $(".chkChannel", page).get().filter(function(c) { - return c.checked - }).map(function(c) { - return c.getAttribute("data-id") - }), user.Policy.EnableAllDevices = $("#chkEnableAllDevices", page).checked(), user.Policy.EnabledDevices = user.Policy.EnableAllDevices ? [] : $(".chkDevice", page).get().filter(function(c) { - return c.checked - }).map(function(c) { - return c.getAttribute("data-id") - }), user.Policy.BlockedChannels = null, user.Policy.BlockedMediaFolders = null, ApiClient.updateUserPolicy(user.Id, user.Policy).then(function() { - onSaveComplete(page) - }) + user.Policy.EnableAllFolders = $("#chkEnableAllFolders", page).checked(); + user.Policy.EnabledFolders = user.Policy.EnableAllFolders ? [] : $(".chkFolder", page).get().filter(function (c) { + return c.checked; + }).map(function (c) { + return c.getAttribute("data-id"); + }); + user.Policy.EnableAllChannels = $("#chkEnableAllChannels", page).checked(); + user.Policy.EnabledChannels = user.Policy.EnableAllChannels ? [] : $(".chkChannel", page).get().filter(function (c) { + return c.checked; + }).map(function (c) { + return c.getAttribute("data-id"); + }); + user.Policy.EnableAllDevices = $("#chkEnableAllDevices", page).checked(); + user.Policy.EnabledDevices = user.Policy.EnableAllDevices ? [] : $(".chkDevice", page).get().filter(function (c) { + return c.checked; + }).map(function (c) { + return c.getAttribute("data-id"); + }); + user.Policy.BlockedChannels = null; + user.Policy.BlockedMediaFolders = null; + ApiClient.updateUserPolicy(user.Id, user.Policy).then(function () { + onSaveComplete(page); + }); } function onSubmit() { var page = $(this).parents(".page"); loading.show(); var userId = getParameterByName("userId"); - return ApiClient.getUser(userId).then(function(result) { - saveUser(result, page) - }), !1 + ApiClient.getUser(userId).then(function (result) { + saveUser(result, page); + }); + return false; } - $(document).on("pageinit", "#userLibraryAccessPage", function() { + + $(document).on("pageinit", "#userLibraryAccessPage", function () { var page = this; - $("#chkEnableAllDevices", page).on("change", function() { - this.checked ? $(".deviceAccessListContainer", page).hide() : $(".deviceAccessListContainer", page).show() - }), $("#chkEnableAllChannels", page).on("change", function() { - this.checked ? $(".channelAccessListContainer", page).hide() : $(".channelAccessListContainer", page).show() - }), page.querySelector("#chkEnableAllFolders").addEventListener("change", function() { - this.checked ? page.querySelector(".folderAccessListContainer").classList.add("hide") : page.querySelector(".folderAccessListContainer").classList.remove("hide") - }), $(".userLibraryAccessForm").off("submit", onSubmit).on("submit", onSubmit) - }).on("pageshow", "#userLibraryAccessPage", function() { + $("#chkEnableAllDevices", page).on("change", function () { + if (this.checked) { + $(".deviceAccessListContainer", page).hide(); + } else { + $(".deviceAccessListContainer", page).show(); + } + }); + $("#chkEnableAllChannels", page).on("change", function () { + if (this.checked) { + $(".channelAccessListContainer", page).hide(); + } else { + $(".channelAccessListContainer", page).show(); + } + }); + page.querySelector("#chkEnableAllFolders").addEventListener("change", function () { + if (this.checked) { + page.querySelector(".folderAccessListContainer").classList.add("hide"); + } else { + page.querySelector(".folderAccessListContainer").classList.remove("hide"); + } + }); + $(".userLibraryAccessForm").off("submit", onSubmit).on("submit", onSubmit); + }).on("pageshow", "#userLibraryAccessPage", function () { var page = this; loading.show(); - var promise1, userId = getParameterByName("userId"); - if (userId) promise1 = ApiClient.getUser(userId); - else { + var promise1; + var userId = getParameterByName("userId"); + + if (userId) { + promise1 = ApiClient.getUser(userId); + } else { var deferred = $.Deferred(); deferred.resolveWith(null, [{ Configuration: {} - }]), promise1 = deferred.promise() + }]); + promise1 = deferred.promise(); } - var promise2 = Dashboard.getCurrentUser(), - promise4 = ApiClient.getJSON(ApiClient.getUrl("Library/MediaFolders", { - IsHidden: !1 - })), - promise5 = ApiClient.getJSON(ApiClient.getUrl("Channels")), - promise6 = ApiClient.getJSON(ApiClient.getUrl("Devices")); - Promise.all([promise1, promise2, promise4, promise5, promise6]).then(function(responses) { - loadUser(page, responses[0], responses[1], responses[2].Items, responses[3].Items, responses[4].Items) - }) - }) -}); \ No newline at end of file + + var promise2 = Dashboard.getCurrentUser(); + var promise4 = ApiClient.getJSON(ApiClient.getUrl("Library/MediaFolders", { + IsHidden: false + })); + var promise5 = ApiClient.getJSON(ApiClient.getUrl("Channels")); + var promise6 = ApiClient.getJSON(ApiClient.getUrl("Devices")); + Promise.all([promise1, promise2, promise4, promise5, promise6]).then(function (responses) { + loadUser(page, responses[0], responses[1], responses[2].Items, responses[3].Items, responses[4].Items); + }); + }); +}); diff --git a/src/controllers/usernew.js b/src/controllers/usernew.js index 10fa6fc4f3..ec80679f8c 100644 --- a/src/controllers/usernew.js +++ b/src/controllers/usernew.js @@ -1,14 +1,16 @@ -define(["jQuery", "loading", "fnchecked", "emby-checkbox"], function($, loading) { +define(["jQuery", "loading", "fnchecked", "emby-checkbox"], function ($, loading) { "use strict"; function loadMediaFolders(page, mediaFolders) { var html = ""; html += '

' + Globalize.translate("HeaderLibraries") + "

"; html += '
'; + for (var i = 0; i < mediaFolders.length; i++) { var folder = mediaFolders[i]; html += '"; } + html += "
"; $(".folderAccess", page).html(html).trigger("create"); $("#chkEnableAllFolders", page).checked(true).trigger("change"); @@ -18,17 +20,21 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox"], function($, loading) var html = ""; html += '

' + Globalize.translate("HeaderChannels") + "

"; html += '
'; + for (var i = 0; i < channels.length; i++) { var folder = channels[i]; html += '"; } + html += "
"; $(".channelAccess", page).show().html(html).trigger("create"); + if (channels.length) { $(".channelAccessContainer", page).show(); } else { $(".channelAccessContainer", page).hide(); } + $("#chkEnableAllChannels", page).checked(true).trigger("change"); } @@ -37,46 +43,51 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox"], function($, loading) $("#txtPassword", page).val(""); loading.show(); var promiseFolders = ApiClient.getJSON(ApiClient.getUrl("Library/MediaFolders", { - IsHidden: false + IsHidden: false })); var promiseChannels = ApiClient.getJSON(ApiClient.getUrl("Channels")); - Promise.all([promiseFolders, promiseChannels]).then(function(responses) { + Promise.all([promiseFolders, promiseChannels]).then(function (responses) { loadMediaFolders(page, responses[0].Items); loadChannels(page, responses[1].Items); loading.hide(); - }) + }); } function saveUser(page) { var user = {}; user.Name = $("#txtUsername", page).val(); user.Password = $("#txtPassword", page).val(); - ApiClient.createUser(user).then(function(user) { + ApiClient.createUser(user).then(function (user) { user.Policy.EnableAllFolders = $("#chkEnableAllFolders", page).checked(); user.Policy.EnabledFolders = []; + if (!user.Policy.EnableAllFolders) { - user.Policy.EnabledFolders = $(".chkFolder", page).get().filter(function(i) { - return i.checked - }).map(function(i) { + user.Policy.EnabledFolders = $(".chkFolder", page).get().filter(function (i) { + return i.checked; + }).map(function (i) { return i.getAttribute("data-id"); }); } + user.Policy.EnableAllChannels = $("#chkEnableAllChannels", page).checked(); user.Policy.EnabledChannels = []; + if (!user.Policy.EnableAllChannels) { - user.Policy.EnabledChannels = $(".chkChannel", page).get().filter(function(i) { - return i.checked - }).map(function(i) { + user.Policy.EnabledChannels = $(".chkChannel", page).get().filter(function (i) { + return i.checked; + }).map(function (i) { return i.getAttribute("data-id"); }); } - ApiClient.updateUserPolicy(user.Id, user.Policy).then(function() { + + ApiClient.updateUserPolicy(user.Id, user.Policy).then(function () { Dashboard.navigate("useredit.html?userId=" + user.Id); }); - }, function(response) { - require(["toast"], function(toast) { + }, function (response) { + require(["toast"], function (toast) { toast(Globalize.translate("DefaultErrorMessage")); }); + loading.hide(); }); } @@ -92,16 +103,16 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox"], function($, loading) loadUser(page); } - $(document).on("pageinit", "#newUserPage", function() { + $(document).on("pageinit", "#newUserPage", function () { var page = this; - $("#chkEnableAllChannels", page).on("change", function() { + $("#chkEnableAllChannels", page).on("change", function () { if (this.checked) { $(".channelAccessListContainer", page).hide(); } else { $(".channelAccessListContainer", page).show(); } }); - $("#chkEnableAllFolders", page).on("change", function() { + $("#chkEnableAllFolders", page).on("change", function () { if (this.checked) { $(".folderAccessListContainer", page).hide(); } else { @@ -109,7 +120,7 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox"], function($, loading) } }); $(".newUserProfileForm").off("submit", onSubmit).on("submit", onSubmit); - }).on("pageshow", "#newUserPage", function() { + }).on("pageshow", "#newUserPage", function () { loadData(this); }); -}); \ No newline at end of file +}); diff --git a/src/controllers/userparentalcontrol.js b/src/controllers/userparentalcontrol.js index 381dc8cea9..2a862912d5 100644 --- a/src/controllers/userparentalcontrol.js +++ b/src/controllers/userparentalcontrol.js @@ -1,185 +1,271 @@ -define(["jQuery", "datetime", "loading", "libraryMenu", "listViewStyle", "paper-icon-button-light"], function($, datetime, loading, libraryMenu) { +define(["jQuery", "datetime", "loading", "libraryMenu", "listViewStyle", "paper-icon-button-light"], function ($, datetime, loading, libraryMenu) { "use strict"; function populateRatings(allParentalRatings, page) { var html = ""; html += ""; - var i, length, rating, ratings = []; + var i; + var length; + var rating; + var ratings = []; + for (i = 0, length = allParentalRatings.length; i < length; i++) { if (rating = allParentalRatings[i], ratings.length) { var lastRating = ratings[ratings.length - 1]; + if (lastRating.Value === rating.Value) { lastRating.Name += "/" + rating.Name; - continue + continue; } } + ratings.push({ Name: rating.Name, Value: rating.Value - }) + }); } - for (i = 0, length = ratings.length; i < length; i++) rating = ratings[i], html += ""; - $("#selectMaxParentalRating", page).html(html) + + for (i = 0, length = ratings.length; i < length; i++) { + rating = ratings[i]; + html += ""; + } + + $("#selectMaxParentalRating", page).html(html); } function loadUnratedItems(page, user) { var items = [{ - name: Globalize.translate("OptionBlockBooks"), - value: "Book" - }, { - name: Globalize.translate("OptionBlockChannelContent"), - value: "ChannelContent" - }, { - name: Globalize.translate("OptionBlockLiveTvChannels"), - value: "LiveTvChannel" - }, { - name: Globalize.translate("OptionBlockMovies"), - value: "Movie" - }, { - name: Globalize.translate("OptionBlockMusic"), - value: "Music" - }, { - name: Globalize.translate("OptionBlockTrailers"), - value: "Trailer" - }, { - name: Globalize.translate("OptionBlockTvShows"), - value: "Series" - }], - html = ""; - html += '

' + Globalize.translate("HeaderBlockItemsWithNoRating") + "

", html += '
'; + name: Globalize.translate("OptionBlockBooks"), + value: "Book" + }, { + name: Globalize.translate("OptionBlockChannelContent"), + value: "ChannelContent" + }, { + name: Globalize.translate("OptionBlockLiveTvChannels"), + value: "LiveTvChannel" + }, { + name: Globalize.translate("OptionBlockMovies"), + value: "Movie" + }, { + name: Globalize.translate("OptionBlockMusic"), + value: "Music" + }, { + name: Globalize.translate("OptionBlockTrailers"), + value: "Trailer" + }, { + name: Globalize.translate("OptionBlockTvShows"), + value: "Series" + }]; + var html = ""; + html += '

' + Globalize.translate("HeaderBlockItemsWithNoRating") + "

"; + html += '
'; + for (var i = 0, length = items.length; i < length; i++) { - var item = items[i], - checkedAttribute = -1 != user.Policy.BlockUnratedItems.indexOf(item.value) ? ' checked="checked"' : ""; - html += '" + var item = items[i]; + var checkedAttribute = -1 != user.Policy.BlockUnratedItems.indexOf(item.value) ? ' checked="checked"' : ""; + html += '"; } - html += "
", $(".blockUnratedItems", page).html(html).trigger("create") + + html += "
"; + $(".blockUnratedItems", page).html(html).trigger("create"); } function loadUser(page, user, allParentalRatings) { - page.querySelector(".username").innerHTML = user.Name, libraryMenu.setTitle(user.Name), loadUnratedItems(page, user), loadBlockedTags(page, user.Policy.BlockedTags), populateRatings(allParentalRatings, page); + page.querySelector(".username").innerHTML = user.Name; + libraryMenu.setTitle(user.Name); + loadUnratedItems(page, user); + loadBlockedTags(page, user.Policy.BlockedTags); + populateRatings(allParentalRatings, page); var ratingValue = ""; - if (user.Policy.MaxParentalRating) + + if (user.Policy.MaxParentalRating) { for (var i = 0, length = allParentalRatings.length; i < length; i++) { var rating = allParentalRatings[i]; - user.Policy.MaxParentalRating >= rating.Value && (ratingValue = rating.Value) + + if (user.Policy.MaxParentalRating >= rating.Value) { + ratingValue = rating.Value; + } } - $("#selectMaxParentalRating", page).val(ratingValue), user.Policy.IsAdministrator ? $(".accessScheduleSection", page).hide() : $(".accessScheduleSection", page).show(), renderAccessSchedule(page, user.Policy.AccessSchedules || []), loading.hide() + } + + $("#selectMaxParentalRating", page).val(ratingValue); + + if (user.Policy.IsAdministrator) { + $(".accessScheduleSection", page).hide(); + } else { + $(".accessScheduleSection", page).show(); + } + + renderAccessSchedule(page, user.Policy.AccessSchedules || []); + loading.hide(); } function loadBlockedTags(page, tags) { - var html = tags.map(function(h) { + var html = tags.map(function (h) { var li = '
'; - return li += '
', li += '

', li += h, li += "

", li += "
", li += '', li += "
" + li += '
'; + li += '

'; + li += h; + li += "

"; + li += "
"; + li += ''; + return li += "
"; }).join(""); - html && (html = '
' + html + "
"); + + if (html) { + html = '
' + html + "
"; + } + var elem = $(".blockedTags", page).html(html).trigger("create"); - $(".btnDeleteTag", elem).on("click", function() { - var tag = this.getAttribute("data-tag"), - newTags = tags.filter(function(t) { - return t != tag - }); - loadBlockedTags(page, newTags) - }) + $(".btnDeleteTag", elem).on("click", function () { + var tag = this.getAttribute("data-tag"); + var newTags = tags.filter(function (t) { + return t != tag; + }); + loadBlockedTags(page, newTags); + }); } function deleteAccessSchedule(page, schedules, index) { - schedules.splice(index, 1), renderAccessSchedule(page, schedules) + schedules.splice(index, 1); + renderAccessSchedule(page, schedules); } function renderAccessSchedule(page, schedules) { - var html = "", - index = 0; - html += schedules.map(function(a) { + var html = ""; + var index = 0; + html += schedules.map(function (a) { var itemHtml = ""; - return itemHtml += '
', itemHtml += '
', itemHtml += '

', itemHtml += Globalize.translate("Option" + a.DayOfWeek), itemHtml += "

", itemHtml += '
' + getDisplayTime(a.StartHour) + " - " + getDisplayTime(a.EndHour) + "
", itemHtml += "
", itemHtml += '', itemHtml += "
", index++, itemHtml + itemHtml += '
'; + itemHtml += '
'; + itemHtml += '

'; + itemHtml += Globalize.translate("Option" + a.DayOfWeek); + itemHtml += "

"; + itemHtml += '
' + getDisplayTime(a.StartHour) + " - " + getDisplayTime(a.EndHour) + "
"; + itemHtml += "
"; + itemHtml += ''; + itemHtml += "
"; + index++; + return itemHtml; }).join(""); var accessScheduleList = page.querySelector(".accessScheduleList"); - accessScheduleList.innerHTML = html, $(".btnDelete", accessScheduleList).on("click", function() { - deleteAccessSchedule(page, schedules, parseInt(this.getAttribute("data-index"))) - }) + accessScheduleList.innerHTML = html; + $(".btnDelete", accessScheduleList).on("click", function () { + deleteAccessSchedule(page, schedules, parseInt(this.getAttribute("data-index"))); + }); } function onSaveComplete(page) { - loading.hide(), require(["toast"], function(toast) { - toast(Globalize.translate("SettingsSaved")) - }) + loading.hide(); + + require(["toast"], function (toast) { + toast(Globalize.translate("SettingsSaved")); + }); } function saveUser(user, page) { - user.Policy.MaxParentalRating = $("#selectMaxParentalRating", page).val() || null, user.Policy.BlockUnratedItems = $(".chkUnratedItem", page).get().filter(function(i) { - return i.checked - }).map(function(i) { - return i.getAttribute("data-itemtype") - }), user.Policy.AccessSchedules = getSchedulesFromPage(page), user.Policy.BlockedTags = getBlockedTagsFromPage(page), ApiClient.updateUserPolicy(user.Id, user.Policy).then(function() { - onSaveComplete(page) - }) + user.Policy.MaxParentalRating = $("#selectMaxParentalRating", page).val() || null; + user.Policy.BlockUnratedItems = $(".chkUnratedItem", page).get().filter(function (i) { + return i.checked; + }).map(function (i) { + return i.getAttribute("data-itemtype"); + }); + user.Policy.AccessSchedules = getSchedulesFromPage(page); + user.Policy.BlockedTags = getBlockedTagsFromPage(page); + ApiClient.updateUserPolicy(user.Id, user.Policy).then(function () { + onSaveComplete(page); + }); } function getDisplayTime(hours) { - var minutes = 0, - pct = hours % 1; - return pct && (minutes = parseInt(60 * pct)), datetime.getDisplayTime(new Date(2e3, 1, 1, hours, minutes, 0, 0)) + var minutes = 0; + var pct = hours % 1; + + if (pct) { + minutes = parseInt(60 * pct); + } + + return datetime.getDisplayTime(new Date(2000, 1, 1, hours, minutes, 0, 0)); } function showSchedulePopup(page, schedule, index) { - schedule = schedule || {}, require(["components/accessschedule/accessschedule"], function(accessschedule) { + schedule = schedule || {}; + + require(["components/accessschedule/accessschedule"], function (accessschedule) { accessschedule.show({ schedule: schedule - }).then(function(updatedSchedule) { - var schedules = getSchedulesFromPage(page); - 1 == index && (index = schedules.length), schedules[index] = updatedSchedule, renderAccessSchedule(page, schedules) - }) - }) + }).then(function (updatedSchedule) { + var schedules = getSchedulesFromPage(page); + + if (-1 == index) { + index = schedules.length; + } + + schedules[index] = updatedSchedule; + renderAccessSchedule(page, schedules); + }); + }); } function getSchedulesFromPage(page) { - return $(".liSchedule", page).map(function() { + return $(".liSchedule", page).map(function () { return { DayOfWeek: this.getAttribute("data-day"), StartHour: this.getAttribute("data-start"), EndHour: this.getAttribute("data-end") - } - }).get() + }; + }).get(); } function getBlockedTagsFromPage(page) { - return $(".blockedTag", page).map(function() { - return this.getAttribute("data-tag") - }).get() + return $(".blockedTag", page).map(function () { + return this.getAttribute("data-tag"); + }).get(); } function showBlockedTagPopup(page) { - require(["prompt"], function(prompt) { + require(["prompt"], function (prompt) { prompt({ label: Globalize.translate("LabelTag") - }).then(function(value) { - var tags = getBlockedTagsFromPage(page); - 1 == tags.indexOf(value) && (tags.push(value), loadBlockedTags(page, tags)) - }) - }) + }).then(function (value) { + var tags = getBlockedTagsFromPage(page); + + if (-1 == tags.indexOf(value)) { + tags.push(value); + loadBlockedTags(page, tags); + } + }); + }); } + window.UserParentalControlPage = { - onSubmit: function() { + onSubmit: function () { var page = $(this).parents(".page"); loading.show(); var userId = getParameterByName("userId"); - return ApiClient.getUser(userId).then(function(result) { - saveUser(result, page) - }), !1 + ApiClient.getUser(userId).then(function (result) { + saveUser(result, page); + }); + return false; } - }, $(document).on("pageinit", "#userParentalControlPage", function() { + }; + $(document).on("pageinit", "#userParentalControlPage", function () { var page = this; - $(".btnAddSchedule", page).on("click", function() { - showSchedulePopup(page, {}, -1) - }), $(".btnAddBlockedTag", page).on("click", function() { - showBlockedTagPopup(page) - }), $(".userParentalControlForm").off("submit", UserParentalControlPage.onSubmit).on("submit", UserParentalControlPage.onSubmit) - }).on("pageshow", "#userParentalControlPage", function() { + $(".btnAddSchedule", page).on("click", function () { + showSchedulePopup(page, {}, -1); + }); + $(".btnAddBlockedTag", page).on("click", function () { + showBlockedTagPopup(page); + }); + $(".userParentalControlForm").off("submit", UserParentalControlPage.onSubmit).on("submit", UserParentalControlPage.onSubmit); + }).on("pageshow", "#userParentalControlPage", function () { var page = this; loading.show(); - var userId = getParameterByName("userId"), - promise1 = ApiClient.getUser(userId), - promise2 = ApiClient.getParentalRatings(); - Promise.all([promise1, promise2]).then(function(responses) { - loadUser(page, responses[0], responses[1]) - }) - }) + var userId = getParameterByName("userId"); + var promise1 = ApiClient.getUser(userId); + var promise2 = ApiClient.getParentalRatings(); + Promise.all([promise1, promise2]).then(function (responses) { + loadUser(page, responses[0], responses[1]); + }); + }); }); diff --git a/src/controllers/userpasswordpage.js b/src/controllers/userpasswordpage.js index d1eef004f6..30ca063278 100644 --- a/src/controllers/userpasswordpage.js +++ b/src/controllers/userpasswordpage.js @@ -1,101 +1,183 @@ -define(["loading", "libraryMenu", "emby-button"], function(loading, libraryMenu) { +define(["loading", "libraryMenu", "emby-button"], function (loading, libraryMenu) { "use strict"; function loadUser(page, params) { var userid = params.userId; - ApiClient.getUser(userid).then(function(user) { - Dashboard.getCurrentUser().then(function(loggedInUser) { - libraryMenu.setTitle(user.Name), page.querySelector(".username").innerHTML = user.Name; - var showPasswordSection = !0, - showLocalAccessSection = !1; - "Guest" == user.ConnectLinkType ? (page.querySelector(".localAccessSection").classList.add("hide"), showPasswordSection = !1) : user.HasConfiguredPassword ? (page.querySelector("#btnResetPassword").classList.remove("hide"), page.querySelector("#fldCurrentPassword").classList.remove("hide"), showLocalAccessSection = !0) : (page.querySelector("#btnResetPassword").classList.add("hide"), page.querySelector("#fldCurrentPassword").classList.add("hide")), showPasswordSection && (loggedInUser.Policy.IsAdministrator || user.Policy.EnableUserPreferenceAccess) ? page.querySelector(".passwordSection").classList.remove("hide") : page.querySelector(".passwordSection").classList.add("hide"), showLocalAccessSection && (loggedInUser.Policy.IsAdministrator || user.Policy.EnableUserPreferenceAccess) ? page.querySelector(".localAccessSection").classList.remove("hide") : page.querySelector(".localAccessSection").classList.add("hide"); + ApiClient.getUser(userid).then(function (user) { + Dashboard.getCurrentUser().then(function (loggedInUser) { + libraryMenu.setTitle(user.Name); + page.querySelector(".username").innerHTML = user.Name; + var showPasswordSection = true; + var showLocalAccessSection = false; + + if ("Guest" == user.ConnectLinkType) { + page.querySelector(".localAccessSection").classList.add("hide"); + showPasswordSection = false; + } else if (user.HasConfiguredPassword) { + page.querySelector("#btnResetPassword").classList.remove("hide"); + page.querySelector("#fldCurrentPassword").classList.remove("hide"); + showLocalAccessSection = true; + } else { + page.querySelector("#btnResetPassword").classList.add("hide"); + page.querySelector("#fldCurrentPassword").classList.add("hide"); + } + + if (showPasswordSection && (loggedInUser.Policy.IsAdministrator || user.Policy.EnableUserPreferenceAccess)) { + page.querySelector(".passwordSection").classList.remove("hide"); + } else { + page.querySelector(".passwordSection").classList.add("hide"); + } + + if (showLocalAccessSection && (loggedInUser.Policy.IsAdministrator || user.Policy.EnableUserPreferenceAccess)) { + page.querySelector(".localAccessSection").classList.remove("hide"); + } else { + page.querySelector(".localAccessSection").classList.add("hide"); + } + var txtEasyPassword = page.querySelector("#txtEasyPassword"); - txtEasyPassword.value = "", user.HasConfiguredEasyPassword ? (txtEasyPassword.placeholder = "******", page.querySelector("#btnResetEasyPassword").classList.remove("hide")) : (txtEasyPassword.removeAttribute("placeholder"), txtEasyPassword.placeholder = "", page.querySelector("#btnResetEasyPassword").classList.add("hide")), page.querySelector(".chkEnableLocalEasyPassword").checked = user.Configuration.EnableLocalPassword - }) - }), page.querySelector("#txtCurrentPassword").value = "", page.querySelector("#txtNewPassword").value = "", page.querySelector("#txtNewPasswordConfirm").value = "" + txtEasyPassword.value = ""; + + if (user.HasConfiguredEasyPassword) { + txtEasyPassword.placeholder = "******"; + page.querySelector("#btnResetEasyPassword").classList.remove("hide"); + } else { + txtEasyPassword.removeAttribute("placeholder"); + txtEasyPassword.placeholder = ""; + page.querySelector("#btnResetEasyPassword").classList.add("hide"); + } + + page.querySelector(".chkEnableLocalEasyPassword").checked = user.Configuration.EnableLocalPassword; + }); + }); + page.querySelector("#txtCurrentPassword").value = ""; + page.querySelector("#txtNewPassword").value = ""; + page.querySelector("#txtNewPasswordConfirm").value = ""; } - return function(view, params) { + + return function (view, params) { function saveEasyPassword() { - var userId = params.userId, - easyPassword = view.querySelector("#txtEasyPassword").value; - easyPassword ? ApiClient.updateEasyPassword(userId, easyPassword).then(function() { - onEasyPasswordSaved(userId) - }) : onEasyPasswordSaved(userId) + var userId = params.userId; + var easyPassword = view.querySelector("#txtEasyPassword").value; + + if (easyPassword) { + ApiClient.updateEasyPassword(userId, easyPassword).then(function () { + onEasyPasswordSaved(userId); + }); + } else { + onEasyPasswordSaved(userId); + } } function onEasyPasswordSaved(userId) { - ApiClient.getUser(userId).then(function(user) { - user.Configuration.EnableLocalPassword = view.querySelector(".chkEnableLocalEasyPassword").checked, ApiClient.updateUserConfiguration(user.Id, user.Configuration).then(function() { - loading.hide(), require(["toast"], function(toast) { - toast(Globalize.translate("MessageSettingsSaved")) - }), loadUser(view, params) - }) - }) + ApiClient.getUser(userId).then(function (user) { + user.Configuration.EnableLocalPassword = view.querySelector(".chkEnableLocalEasyPassword").checked; + ApiClient.updateUserConfiguration(user.Id, user.Configuration).then(function () { + loading.hide(); + + require(["toast"], function (toast) { + toast(Globalize.translate("MessageSettingsSaved")); + }); + + loadUser(view, params); + }); + }); } function savePassword() { - var userId = params.userId, - currentPassword = view.querySelector("#txtCurrentPassword").value, - newPassword = view.querySelector("#txtNewPassword").value; + var userId = params.userId; + var currentPassword = view.querySelector("#txtCurrentPassword").value; + var newPassword = view.querySelector("#txtNewPassword").value; + if (view.querySelector("#fldCurrentPassword").classList.contains("hide")) { // Firefox does not respect autocomplete=off, so clear it if the field is supposed to be hidden (and blank) // This should only happen when user.HasConfiguredPassword is false, but this information is not passed on currentPassword = ""; } - ApiClient.updateUserPassword(userId, currentPassword, newPassword).then(function() { - loading.hide(), require(["toast"], function(toast) { - toast(Globalize.translate("PasswordSaved")) - }), loadUser(view, params) - }, function() { - loading.hide(), Dashboard.alert({ + + ApiClient.updateUserPassword(userId, currentPassword, newPassword).then(function () { + loading.hide(); + + require(["toast"], function (toast) { + toast(Globalize.translate("PasswordSaved")); + }); + + loadUser(view, params); + }, function () { + loading.hide(); + Dashboard.alert({ title: Globalize.translate("HeaderLoginFailure"), message: Globalize.translate("MessageInvalidUser") - }) - }) + }); + }); } function onSubmit(e) { var form = this; - return form.querySelector("#txtNewPassword").value != form.querySelector("#txtNewPasswordConfirm").value ? require(["toast"], function(toast) { - toast(Globalize.translate("PasswordMatchError")) - }) : (loading.show(), savePassword()), e.preventDefault(), !1 + + if (form.querySelector("#txtNewPassword").value != form.querySelector("#txtNewPasswordConfirm").value) { + require(["toast"], function (toast) { + toast(Globalize.translate("PasswordMatchError")); + }); + } else { + loading.show(); + savePassword(); + } + + e.preventDefault(); + return false; } function onLocalAccessSubmit(e) { - return loading.show(), saveEasyPassword(), e.preventDefault(), !1 + loading.show(); + saveEasyPassword(); + e.preventDefault(); + return false; } function resetPassword() { var msg = Globalize.translate("PasswordResetConfirmation"); - require(["confirm"], function(confirm) { - confirm(msg, Globalize.translate("PasswordResetHeader")).then(function() { + + require(["confirm"], function (confirm) { + confirm(msg, Globalize.translate("PasswordResetHeader")).then(function () { var userId = params.userId; - loading.show(), ApiClient.resetUserPassword(userId).then(function() { - loading.hide(), Dashboard.alert({ + loading.show(); + ApiClient.resetUserPassword(userId).then(function () { + loading.hide(); + Dashboard.alert({ message: Globalize.translate("PasswordResetComplete"), title: Globalize.translate("PasswordResetHeader") - }), loadUser(view, params) - }) - }) - }) + }); + loadUser(view, params); + }); + }); + }); } function resetEasyPassword() { var msg = Globalize.translate("PinCodeResetConfirmation"); - require(["confirm"], function(confirm) { - confirm(msg, Globalize.translate("HeaderPinCodeReset")).then(function() { + + require(["confirm"], function (confirm) { + confirm(msg, Globalize.translate("HeaderPinCodeReset")).then(function () { var userId = params.userId; - loading.show(), ApiClient.resetEasyPassword(userId).then(function() { - loading.hide(), Dashboard.alert({ + loading.show(); + ApiClient.resetEasyPassword(userId).then(function () { + loading.hide(); + Dashboard.alert({ message: Globalize.translate("PinCodeResetComplete"), title: Globalize.translate("HeaderPinCodeReset") - }), loadUser(view, params) - }) - }) - }) + }); + loadUser(view, params); + }); + }); + }); } - view.querySelector(".updatePasswordForm").addEventListener("submit", onSubmit), view.querySelector(".localAccessForm").addEventListener("submit", onLocalAccessSubmit), view.querySelector("#btnResetEasyPassword").addEventListener("click", resetEasyPassword), view.querySelector("#btnResetPassword").addEventListener("click", resetPassword), view.addEventListener("viewshow", function() { - loadUser(view, params) - }) - } + + view.querySelector(".updatePasswordForm").addEventListener("submit", onSubmit); + view.querySelector(".localAccessForm").addEventListener("submit", onLocalAccessSubmit); + view.querySelector("#btnResetEasyPassword").addEventListener("click", resetEasyPassword); + view.querySelector("#btnResetPassword").addEventListener("click", resetPassword); + view.addEventListener("viewshow", function () { + loadUser(view, params); + }); + }; }); diff --git a/src/controllers/wizardfinishpage.js b/src/controllers/wizardfinishpage.js index 180af64b58..8242a16cb4 100644 --- a/src/controllers/wizardfinishpage.js +++ b/src/controllers/wizardfinishpage.js @@ -6,7 +6,7 @@ define(["loading"], function (loading) { ApiClient.ajax({ url: ApiClient.getUrl("Startup/Complete"), type: "POST" - }).then(function() { + }).then(function () { loading.hide(); window.location.href = "index.html"; }); diff --git a/src/index.html b/src/index.html index bc9c7b64c5..d95784a3dc 100644 --- a/src/index.html +++ b/src/index.html @@ -98,8 +98,8 @@
-
-
+
+
diff --git a/src/scripts/apploader.js b/src/scripts/apploader.js index 9067ae6070..4b5d2e8eec 100644 --- a/src/scripts/apploader.js +++ b/src/scripts/apploader.js @@ -20,7 +20,7 @@ } injectScriptElement( - self.Promise ? "./bower_components/alameda/alameda.js" : "./bower_components/requirejs/require.js", + self.Promise ? "./libraries/alameda.js" : "./libraries/require.js", function() { // onload of require library injectScriptElement("./scripts/site.js"); diff --git a/src/scripts/librarymenu.js b/src/scripts/librarymenu.js index 8d282b003e..ad15b8538e 100644 --- a/src/scripts/librarymenu.js +++ b/src/scripts/librarymenu.js @@ -52,14 +52,6 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " headerSearchButton.classList.remove("hide"); } - if (headerSettingsButton) { - if (user.localUser.Policy.IsAdministrator) { - headerSettingsButton.classList.remove("hide"); - } else { - headerSettingsButton.classList.add("hide"); - } - } - headerCastButton.classList.remove("hide"); } else { headerHomeButton.classList.add("hide"); @@ -68,10 +60,6 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " if (headerSearchButton) { headerSearchButton.classList.add("hide"); } - - if (headerSettingsButton) { - headerSettingsButton.classList.add("hide"); - } } requiresUserRefresh = false; @@ -95,10 +83,6 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " Dashboard.navigate("mypreferencesmenu.html"); } - function onSettingsClick(e) { - Dashboard.navigate("dashboard.html"); - } - function onHeaderHomeButtonClick() { Dashboard.navigate("home.html"); } @@ -122,12 +106,9 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " headerUserButton.addEventListener("click", onHeaderUserButtonClick); headerHomeButton.addEventListener("click", onHeaderHomeButtonClick); - initHeadRoom(skinHeader); headerCastButton.addEventListener("click", onCastButtonClicked); - if (headerSettingsButton) { - headerSettingsButton.addEventListener("click", onSettingsClick); - } + initHeadRoom(skinHeader); } function onCastButtonClicked() { @@ -747,7 +728,6 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " var headerBackButton; var headerUserButton; var currentUser; - var headerSettingsButton; var headerCastButton; var headerSearchButton; var enableLibraryNavDrawer = !layoutManager.tv; @@ -873,23 +853,20 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", " html += ''; html += ''; html += ''; - - if (!layoutManager.mobile) { - html += ''; - } - html += "
"; html += "
"; html += '
'; html += "
"; + skinHeader.classList.add("skinHeader-withBackground"); + skinHeader.classList.add("skinHeader-blurred"); skinHeader.innerHTML = html; + headerHomeButton = skinHeader.querySelector(".headerHomeButton"); headerUserButton = skinHeader.querySelector(".headerUserButton"); - headerSettingsButton = skinHeader.querySelector(".headerSettingsButton"); headerCastButton = skinHeader.querySelector(".headerCastButton"); headerSearchButton = skinHeader.querySelector(".headerSearchButton"); - skinHeader.classList.add("skinHeader-blurred"); + lazyLoadViewMenuBarImages(); bindMenuEvents(); })(); diff --git a/src/strings/cs.json b/src/strings/cs.json index 3d03fc9455..5d53076d31 100644 --- a/src/strings/cs.json +++ b/src/strings/cs.json @@ -13,7 +13,7 @@ "AllChannels": "Všechny kanály", "AllEpisodes": "Všechny epizody", "AllLanguages": "Všechny jazyky", - "AllowHWTranscodingHelp": "Pokud nastavíte, povolíte tuneru překódování v reálném čase. Může snížit zátěž překódovávání požadované Jellyfin serverem.", + "AllowHWTranscodingHelp": "Povolit tuneru překódování v reálném čase. Může snížit zátěž překódovávání požadované Jellyfin serverem.", "AlwaysPlaySubtitles": "Vždy zobrazit titulky", "AlwaysPlaySubtitlesHelp": "Titulky odpovídající jazykové předvolbě se načtou bez ohledu na jazyk audia.", "Anytime": "Kdykoliv", @@ -30,7 +30,7 @@ "BirthDateValue": "Narozen: {0}", "BirthLocation": "Místo narození", "BirthPlaceValue": "Místo narození: {0}", - "BookLibraryHelp": "Audio a textové knihy jsou podporovány. Přečtěte si {0}pravidla pro názvy knih v Jellyfin{1}.", + "BookLibraryHelp": "Audio a textové knihy jsou podporovány. Přečtěte si {0}pravidla pro názvy knih {1}.", "Books": "Knihy", "Box": "Pouzdro", "BoxRear": "Zadní část pouzdra", @@ -157,7 +157,7 @@ "Dislike": "Nemám rád", "Display": "Zobrazení", "DisplayMissingEpisodesWithinSeasons": "Zobrazit chybějící epizody", - "DisplayMissingEpisodesWithinSeasonsHelp": "Toto musí být zapnuto pro knihovny TV v nastavení Jellyfin serveru.", + "DisplayMissingEpisodesWithinSeasonsHelp": "Toto musí být zapnuto pro knihovny TV v nastavení serveru.", "DisplayModeHelp": "Zvolte typ obrazovky, na které používáte Jellyfin.", "DoNotRecord": "Nenahrávat", "Down": "Dolů", @@ -522,7 +522,7 @@ "LabelEnableDlnaClientDiscoveryInterval": "Čas pro vyhledání klienta (sekund)", "LabelEnableDlnaClientDiscoveryIntervalHelp": "Určuje dobu trvání v sekundách mezi SSDP vyhledávání prováděných pomocí Jellyfin.", "LabelEnableDlnaDebugLogging": "Povolit DLNA protokolování (pro ladění)", - "LabelEnableDlnaDebugLoggingHelp": "Toto nastavení vytváří velmi velké soubory se záznamy a doporučuje se pouze v případě problémů.", + "LabelEnableDlnaDebugLoggingHelp": "Vytváří velké soubory se záznamy a doporučuje se používat pouze pro potřeby odstraňování problémů.", "LabelEnableDlnaPlayTo": "Povolit DLNA přehrávání", "LabelEnableDlnaPlayToHelp": "Jellyfin dokáže detekovat zařízení v rámci vaší sítě a nabízí možnost jeho dálkového ovládání.", "LabelEnableDlnaServer": "Povolit Dlna Server", @@ -611,9 +611,9 @@ "LabelMethod": "Metoda:", "LabelMinBackdropDownloadWidth": "Maximální šířka pro stažení pozadí:", "LabelMinResumeDuration": "Minimální doba trvání:", - "LabelMinResumeDurationHelp": "Videa kratší než tato délka nebudou pozastavitelné", + "LabelMinResumeDurationHelp": "Videa kratší než tato délka nebudou pozastavitelné.", "LabelMinResumePercentage": "Minimální procento pro přerušení:", - "LabelMinResumePercentageHelp": "Tituly budou označeny jako \"nepřehráno\", pokud budou zastaveny před tímto časem", + "LabelMinResumePercentageHelp": "Tituly budou označeny jako \"nepřehráno\", pokud budou zastaveny před tímto časem.", "LabelMinScreenshotDownloadWidth": "Minimální šířka screenshotu obrazovky:", "LabelModelDescription": "Popis modelu", "LabelModelName": "Název modelu", @@ -1027,7 +1027,7 @@ "PlaybackErrorNotAllowed": "V současné době nejste oprávněni přehrávat tento obsah. Pro více informací se obraťte se na správce systému.", "PlaybackErrorPlaceHolder": "Chcete-li toto video přehrát, vložte disk.", "Played": "Přehráno", - "Playlists": "Playlisty", + "Playlists": "Seznamy skladeb", "PleaseAddAtLeastOneFolder": "Přidejte prosím nejméně jednu složku do této knihovny pomocí tlačítka Přidat.", "PleaseConfirmPluginInstallation": "Pro potvrzení, že jste si přečetli text výše a chcete pokračovat v instalaci zásuvných modulů, klikněte na tlačítko OK.", "PleaseEnterNameOrId": "Prosím, zadejte název nebo externí Id.", @@ -1230,7 +1230,7 @@ "AllowMediaConversion": "Povolit konverzi médií", "AllowMediaConversionHelp": "Povolit nebo zakázat přístup k funkci konverze médií.", "AllowOnTheFlySubtitleExtraction": "Povolit extrahování titulků za běhu", - "AllowOnTheFlySubtitleExtractionHelp": "Vložené titulky mohou být extrahovány z videa a dodávány do aplikace Jellyfin ve formě prostého textu, aby se zabránilo překódování videa. V některých systémech to může trvat dlouho a způsobit zasekávání přehrávání videa. Při vypnutí funkce budou během překódování obsažené titulky vypáleny do obrazu, pokud je klientské zařízení nativně nepodporuje.", + "AllowOnTheFlySubtitleExtractionHelp": "Vložené titulky mohou být extrahovány z videa a dodávány do aplikací ve formě prostého textu, aby se zabránilo překódování videa. V některých systémech to může trvat dlouho a způsobit zasekávání přehrávání videa. Při vypnutí funkce budou během překódování obsažené titulky vypáleny do obrazu, pokud je klientské zařízení nativně nepodporuje.", "AllowRemoteAccess": "Povolit vzdálené připojení na server Jellyfin.", "AllowRemoteAccessHelp": "Pokud není zapnuto, všechna vzdálená připojení budou blokována.", "AllowSeasonalThemesHelp": "Pokud je povoleno, sezónní motivy občas přepíšou nastavení vašeho motivu.", @@ -1249,7 +1249,7 @@ "Blacklist": "Blacklist", "BobAndWeaveWithHelp": "Bob and weave (vyšší kvalita, ale pomalejší)", "Browse": "Procházet", - "BurnSubtitlesHelp": "Určuje, zda má server vypalovat titulky při převodu videa v závislosti na formátu titulků. Vynechání vypalování titulků zlepší výkon serveru. Chcete-li vypálit grafické formáty (např. VOBSUB, PGS, SUB / IDX atd.), stejně jako některé titulky ASS / SSA, vyberte možnost Auto", + "BurnSubtitlesHelp": "Určuje, zda má server vypalovat titulky při převodu videa v závislosti na formátu titulků. Vynechání vypalování titulků zlepší výkon serveru. Chcete-li vypálit grafické formáty (VOBSUB, PGS, SUB / IDX atd.) a některé titulky ASS / SSA, vyberte možnost Auto.", "ButtonInfo": "Info", "ButtonMenu": "Menu", "ButtonOk": "Ok", @@ -1304,7 +1304,7 @@ "HandledByProxy": "Zpracováno reverzním proxy", "HeaderAddLocalUser": "Přidat místního uživatele", "HeaderAllowMediaDeletionFrom": "Povolit smazání médií z", - "HeaderAppearsOn": "Appears On", + "HeaderAppearsOn": "Objeví se", "HeaderAudio": "Audio", "HeaderBlockItemsWithNoRating": "Blokovat položky s žádnými nebo nerozpoznanými informacemi o hodnocení:", "HeaderCameraUploadHelp": "Aplikace Jellyfin mohou automaticky nahrávat fotografie z mobilních zařízení do serveru Jellyfin.", @@ -1322,8 +1322,8 @@ "HeaderImageOptions": "Volby obrázku", "HeaderInviteWithJellyfinConnect": "Pozvat s Jellyfin Connect", "HeaderKodiMetadataHelp": "Chcete-li povolit nebo zakázat Nfo metadata, upravte nastavení knihovny v sekci ukládání metadat.", - "HeaderLiveTV": "Live TV", - "HeaderLiveTv": "Live TV", + "HeaderLiveTV": "Živá TV", + "HeaderLiveTv": "Živá TV", "HeaderLiveTvTunerSetup": "Nastavení tuneru Live TV", "HeaderMenu": "Menu", "HeaderNewDevices": "Nové zařízení", @@ -1350,7 +1350,7 @@ "LabelAlbum": "Album:", "LabelAllowedRemoteAddresses": "Filtr vzdálené IP adresy:", "LabelAllowedRemoteAddressesMode": "Režim filtru vzdálené IP adresy:", - "LabelAudioCodec": "Audio: {0}", + "LabelAudioCodec": "Audio kodek:", "LabelAutomaticallyRefreshInternetMetadataEvery": "Automaticky aktualizovat metadata z internetu:", "LabelBlockContentWithTags": "Blokovat položky s tagy:", "LabelBurnSubtitles": "Vypálit titulky:", @@ -1369,8 +1369,8 @@ "LabelEnableHardwareDecodingFor": "Povolit hardwarové dekódování pro:", "LabelHomeNetworkQuality": "Kvalita na domácí síti:", "LabelInternetQuality": "Kvalita na internetu:", - "LabelKodiMetadataUser": "Uložení dat sledování uživatele do nfo pro:", - "LabelKodiMetadataUserHelp": "Povolte toto nastavení pro uložení dat sledování do souborů NFO pro jiné aplikace, které chcete používat.", + "LabelKodiMetadataUser": "Uložit data sledování uživatele do NFO souboru pro:", + "LabelKodiMetadataUserHelp": "Uložit sledovaná data o přehrávání pro využití dalšími aplikacemi.", "LabelLanNetworks": "Sítě LAN:", "LabelLimit": "Limit:", "LabelMaxStreamingBitrate": "Maximální kvalita streamování:", @@ -1383,7 +1383,7 @@ "LabelSecureConnectionsMode": "Režim zabezpečeného připojení:", "LabelServerHost": "Host:", "LabelSimultaneousConnectionLimit": "Limit současně běžících streamů:", - "LabelSkin": "Skin:", + "LabelSkin": "Vzhled:", "LabelSortBy": "Řadit podle:", "LabelSortOrder": "Pořadí řazení:", "LabelSpecialSeasonsDisplayName": "Zobrazovaný název pro zvláštní sezónu:", @@ -1395,14 +1395,14 @@ "LabelTypeText": "Text", "LabelUrl": "URL:", "LabelUserAgent": "User agent:", - "LabelUserRemoteClientBitrateLimitHelp": "Toto přepíše výchozí globální hodnotu nastavenou v nastavení přehrávání serveru.", + "LabelUserRemoteClientBitrateLimitHelp": "Přepíše výchozí globální hodnotu nastavenou v nastavení přehrávání serveru.", "LabelVideo": "Video:", - "LabelVideoCodec": "Video: {0}", - "LeaveBlankToNotSetAPassword": "Volitelné - ponechat prázdné pro nastavení bez hesla", + "LabelVideoCodec": "Video kodek:", + "LeaveBlankToNotSetAPassword": "Můžete ponechat prázdné pro nastavení bez hesla.", "LetterButtonAbbreviation": "A", "LinkApi": "API", "LinksValue": "Odkazy: {0}", - "LiveTV": "Live TV", + "LiveTV": "Živá TV", "LiveTvFeatureDescription": "Streamujte televizní vysílání do libovolné aplikace Jellyfin s kompatibilním televizním tunerem instalovaným na serveru Jellyfin.", "Logo": "Logo", "ManageLibrary": "Spravovat knihovnu", @@ -1411,7 +1411,7 @@ "MediaInfoStreamTypeAudio": "Audio", "MediaInfoStreamTypeData": "Data", "MediaInfoStreamTypeVideo": "Video", - "AuthProviderHelp": "Vyberte poskytovatele ověřování, který bude použit k ověření hesla tohoto uživatele", + "AuthProviderHelp": "Vyberte poskytovatele ověřování, který bude použit k ověření hesla tohoto uživatele.", "HeaderFavoriteMovies": "Oblíbená videa", "HeaderFavoriteShows": "Oblíbené seriály", "HeaderFavoriteEpisodes": "Oblíbené epizody", @@ -1420,7 +1420,7 @@ "HeaderFavoriteSongs": "Oblíbená hudba", "HeaderRestartingServer": "Restartování serveru", "LabelAuthProvider": "Poskytovatel ověření:", - "LabelServerNameHelp": "Tento název bude použit k identifikaci tohoto serveru. Pokud zůstane prázdné, bude použit název počítače.", + "LabelServerNameHelp": "Tento název bude použit k identifikaci serveru a bude výchozí pro název počítače serveru.", "LabelPasswordResetProvider": "Poskytovatel obnovy hesla:", "LabelServerName": "Název serveru:", "LabelTranscodePath": "Cesta pro překódování:", @@ -1439,16 +1439,16 @@ "MessageNoCollectionsAvailable": "Kolekce vám umožní vychutnat si osobní seskupení filmů, seriálů a hudebních alb. Chcete-li je začít vytvářet, klikněte na tlačítko +.", "MessagePleaseWait": "Prosím, čekejte. Může to trvat několik minut.", "Metadata": "Metadata", - "MovieLibraryHelp": "Podívejte se na {0}průvodce pojmenováním filmů Jellyfin{1}.", + "MovieLibraryHelp": "Podívejte se na {0}průvodce pojmenováním filmů{1}.", "Never": "Nikdy", "NextUp": "Další", "NoNewDevicesFound": "Nebyla nalezena žádná nová zařízení. Chcete-li přidat nový tuner, zavřete tento dialog a zadejte informace o zařízení ručně.", - "OnlyImageFormats": "Pouze obrazové formáty (VOBSUB, PGS, SUB/IDX, atd.)", + "OnlyImageFormats": "Pouze obrazové formáty (VOBSUB, PGS, SUB, atd.)", "Option3D": "3D", "OptionAlbum": "Album", "OptionAllowMediaPlaybackTranscodingHelp": "Omezení přístupu k překódování může způsobit selhání přehrávání v aplikacích Jellyfin kvůli nepodporovaným formátům médií.", "OptionAllowSyncTranscoding": "Povolit stahování a synchronizaci médií, které vyžaduje překódování", - "OptionBluray": "Bluray", + "OptionBluray": "Blu-ray", "OptionCaptionInfoExSamsung": "CaptionInfoEx (Samsung)", "OptionDownloadBannerImage": "Banner", "OptionDownloadBoxImage": "Box", @@ -1456,7 +1456,7 @@ "OptionIsHD": "HD", "OptionIsSD": "SD", "OptionLoginAttemptsBeforeLockout": "Určuje, kolik chybných pokusů o přihlášení lze provést před zablokováním.", - "OptionLoginAttemptsBeforeLockoutHelp": "0 znamená zdědění výchozí hodnoty 3 pro non-admin a 5 pro admin, -1 deaktivuje uzamykání", + "OptionLoginAttemptsBeforeLockoutHelp": "0 znamená zdědění výchozí hodnoty 3 pokusů pro běžné uživatele a 5 pro administrátory. Nastavení na -1 deaktivuje funkci.", "OptionMax": "Max", "OptionProfileAudio": "Audio", "OptionProfileVideo": "Video", @@ -1489,14 +1489,14 @@ "Sort": "Třídit", "StatsForNerds": "Statistiky pro šprty", "SubtitleAppearanceSettingsAlsoPassedToCastDevices": "Tato nastavení platí také pro jakékoli přehrávání na Chromecastu spuštěné tímto zařízením.", - "SubtitleAppearanceSettingsDisclaimer": "Tato nastavení se nevztahuje na grafické titulky (PGS, DVD atd.) nebo titulky, které mají vlastní vložené styly (ASS / SSA).", + "SubtitleAppearanceSettingsDisclaimer": "Tato nastavení se nevztahuje na grafické titulky (PGS, DVD atd.) nebo ASS/SSA titulky, které mají vlastní vložené styly.", "SubtitleDownloadersHelp": "Povolte a zařaďte preferované stahovače titulků v pořadí podle priority.", "SubtitleSettings": "Nastavení titulků", "SubtitleSettingsIntro": "Chcete-li nastavit výchozí vzhled a jazyk titulků, zastavte přehrávání videa a klepněte na ikonu uživatele v pravé horní části aplikace.", "TV": "TV", "TabDirectPlay": "Přímé přehrávání", "TabInfo": "Info", - "TabLiveTV": "Live TV", + "TabLiveTV": "Živá TV", "TabMetadata": "Metadata", "TabPlaylist": "Playlist", "TabServer": "Server", @@ -1504,10 +1504,10 @@ "ThemeSongs": "Tematická hudba", "ThemeVideos": "Tematická videa", "Trailers": "Trailery", - "TvLibraryHelp": "Podívejte se na {0}průvodce pojmenováním TV Jellyfin{1}.", + "TvLibraryHelp": "Podívejte se na {0}průvodce pojmenováním TV pořadů{1}.", "Uniform": "Uniformní", "Unplayed": "Nepřehrané", - "UserAgentHelp": "V případě potřeby zadejte vlastní hlavičku user agenta http.", + "UserAgentHelp": "Zadejte vlastní HTTP hlavičku user agenta.", "ValueMinutes": "{0} min", "ValueOneAlbum": "1 album", "ValueOneSong": "1 skladba", @@ -1518,8 +1518,8 @@ "HeaderHome": "Domů", "DashboardOperatingSystem": "Operační systém: {0}", "DashboardArchitecture": "Architektura: {0}", - "LaunchWebAppOnStartup": "Spusťte webovou aplikaci Jellyfin ve svém webovém prohlížeči po nastartování Jellyfin serveru", - "LaunchWebAppOnStartupHelp": "Toto otevře se webovou aplikaci ve vašem výchozím webovém prohlížeči, když se spustí server Jellyfin. K tomu nedochází při použití funkce restartování serveru.", + "LaunchWebAppOnStartup": "Spustit webové rozhraní po spustění serveru", + "LaunchWebAppOnStartupHelp": "Otevře se webový klient ve vašem výchozím webovém prohlížeči, když server se spustí. K tomu nedochází při použití funkce restartování serveru.", "MessageNoServersAvailable": "Pomocí automatického zjišťování nebyly nalezeny žádné servery.", "OptionBanner": "Banner", "OptionList": "Seznam", @@ -1532,5 +1532,27 @@ "MusicArtist": "Interpret", "MusicVideo": "Videoklip", "SubtitleOffset": "Nastavení titulků", - "TabNetworking": "Vytváření sítí" + "TabNetworking": "Vytváření sítí", + "MusicLibraryHelp": "Prostudujte si {0}průvodce pojmenováním hudby{1}.", + "MoreMediaInfo": "Informace o médiu", + "LabelVideoBitrate": "Datový tok videa:", + "LabelTranscodingProgress": "Průběh překódování:", + "LabelTranscodingFramerate": "Snimková frekvence pro překódování:", + "LabelSize": "Velikost:", + "LabelPleaseRestart": "Změny se projeví až po ručním obnovení webového klienta.", + "LabelPlayMethod": "Způsob přehrání:", + "LabelPlayer": "Přehrávač:", + "LabelFolder": "Složka:", + "LabelBaseUrlHelp": "Zde můžete přidat vlastní podsložku aby bylo možné přistupovat na server z unikátnější adresy.", + "LabelBaseUrl": "Výchozí URL:", + "LabelBitrate": "Datový tok:", + "LabelAudioSampleRate": "Vzorkovací frekvence zvuku:", + "LabelAudioChannels": "Počet kanálů zvuku:", + "LabelAudioBitrate": "Datový tok zvuku:", + "LabelAudioBitDepth": "Bitová hloubka zvuku:", + "HeaderFavoriteBooks": "Oblíbené knihy", + "FetchingData": "Načtení dalších dat", + "CopyStreamURLSuccess": "Úspěšně zkopírovaná URL.", + "CopyStreamURL": "Kopírovat URL adresu streamu", + "ButtonAddImage": "Přidat obrázek" } diff --git a/src/strings/he.json b/src/strings/he.json index bf17cc4e7f..6add390ce3 100644 --- a/src/strings/he.json +++ b/src/strings/he.json @@ -509,5 +509,8 @@ "Writer": "כותב", "Albums": "אלבומים", "Artists": "אמנים", - "Books": "ספרים" + "Books": "ספרים", + "Absolute": "מוחלט", + "AccessRestrictedTryAgainLater": "הגישה כרגע מוגבלת. אנא נסה שוב מאוחר יותר.", + "AddedOnValue": "נוסף {0}" } diff --git a/src/strings/hu.json b/src/strings/hu.json index 1b5a307718..8d60f299e8 100644 --- a/src/strings/hu.json +++ b/src/strings/hu.json @@ -710,7 +710,7 @@ "HeaderActivity": "Tevékenység", "HeaderAdditionalParts": "További részek", "HeaderAdmin": "Adminisztrátor", - "HeaderAlbumArtists": "Album Előadók", + "HeaderAlbumArtists": "Album előadók", "HeaderAlert": "Figyelem", "HeaderAllowMediaDeletionFrom": "Média törlés engedélyezése", "HeaderApiKey": "API Kulcs", @@ -1300,7 +1300,7 @@ "MessageNoServersAvailable": "Az automatikus kiszolgálókeresés nem talált szervert.", "OptionLoginAttemptsBeforeLockout": "Meghatározza, hogy hány érvénytelen bejelentkezési kísérlet történhet zárolás előtt.", "TabNetworking": "Hálózat", - "HeaderFavoriteArtists": "Kedvenc Előadók", + "HeaderFavoriteArtists": "Kedvenc előadók", "SmallCaps": "Kiskapitális", "AllowOnTheFlySubtitleExtractionHelp": "A beágyazott feliratokat ki lehet távolítani a videókból és elküldeni a Jellyfin alkalmazásoknak sima szöveg formátumba, hogy ne legyen átkódolás. Néhány eszközön ez hosszú ideig is eltarthat, valamint a videó lejátszás megakadhat az eltávolítási folyamat futása közben. Ezt kikapcsolva a beágyazott feliratok videó átkódolással beégetésre kerülnek azon kliens eszközökre melyek nem támogatják a külső feliratokat.", "Art": "ClearArt", @@ -1321,10 +1321,10 @@ "HeaderContinueListening": "Folyamatban lévő zenék", "HeaderDeleteTaskTrigger": "Feladatvezérlő törlése", "HeaderFavoriteMovies": "Kedvenc Filmek", - "HeaderFavoriteShows": "Kedvenc Sorozatok", - "HeaderFavoriteEpisodes": "Kedvenc Epizódok", - "HeaderFavoriteAlbums": "Kedvenc Albumok", - "HeaderFavoriteSongs": "Kedvenc Dalok", + "HeaderFavoriteShows": "Kedvenc sorozatok", + "HeaderFavoriteEpisodes": "Kedvenc epizódok", + "HeaderFavoriteAlbums": "Kedvenc albumok", + "HeaderFavoriteSongs": "Kedvenc dalok", "HeaderFavoriteVideos": "Kedvenc Videók", "HeaderGuideProviders": "TV műsorújság Szolgáltatók", "HeaderHome": "Kezdőlap", diff --git a/src/strings/nl.json b/src/strings/nl.json index 9f31521cd5..38f529af9d 100644 --- a/src/strings/nl.json +++ b/src/strings/nl.json @@ -1327,5 +1327,6 @@ "LabelProfileVideoCodecs": "Video codecs:", "LabelProtocolInfo": "Protocol info:", "LabelServerName": "Server naam:", - "LabelSkin": "Skin:" + "LabelSkin": "Skin:", + "ButtonAddImage": "Voeg afbeelding toe" } diff --git a/src/strings/tr.json b/src/strings/tr.json index e2dde03926..f517eb10e9 100644 --- a/src/strings/tr.json +++ b/src/strings/tr.json @@ -439,5 +439,121 @@ "EnableNextVideoInfoOverlay": "Oynatma sırasında bir sonraki video bilgisini göster", "EnablePhotosHelp": "Görüntüler diğer medya dosyalarıyla birlikte algılanacak ve gösterilecektir.", "EnableCinemaMode": "Sinema Modu", - "EnableColorCodedBackgrounds": "Renk kodlu arka planlar" + "EnableColorCodedBackgrounds": "Renk kodlu arka planlar", + "HeaderGuideProviders": "TV Rehberi Veri Sağlayıcıları", + "HeaderGenres": "Türler", + "HeaderForgotPassword": "Parolanızı mı unuttunuz", + "HeaderForKids": "Çocuklar için", + "HeaderFetcherSettings": "Alıcı Ayarları", + "HeaderFetchImages": "Görüntüleri Getir:", + "HeaderFeatures": "Özellikleri", + "HeaderFeatureAccess": "Özellik Erişimi", + "HeaderFavoriteVideos": "Favori Videolar", + "HeaderFavoriteMovies": "Favori Filmler", + "HeaderFavoriteBooks": "favori kitaplar", + "HeaderExternalIds": "Dış kimlikler:", + "HeaderError": "Hata", + "HeaderEpisodes": "Bölümler", + "HeaderEnabledFieldsHelp": "Kilitlemek ve verilerinin değişmesini önlemek için bir alanın işaretini kaldırın.", + "HeaderEnabledFields": "Etkin Alanlar", + "HeaderEditImages": "Görüntüleri Düzenle", + "HeaderDownloadSync": "İndir ve Eşitle", + "HeaderDisplay": "Görüntüle", + "HeaderDirectPlayProfileHelp": "Aygıtın yerel olarak hangi biçimlerde kullanılabileceğini göstermek için doğrudan oynatma profilleri ekleyin.", + "HeaderDirectPlayProfile": "Doğrudan Oyun Profili", + "HeaderDevices": "Cihazlar", + "HeaderDeveloperInfo": "Geliştirici Bilgisi", + "HeaderDetectMyDevices": "Cihazlarımı Algıla", + "HeaderDeleteTaskTrigger": "Görev Tetikleyicisini Sil", + "HeaderDeleteProvider": "Sağlayıcıyı Sil", + "HeaderDeleteItems": "Ürünleri sil", + "HeaderDeleteItem": "Öğeyi sil", + "HeaderDeleteDevice": "Cihazı Sil", + "HeaderDefaultRecordingSettings": "Varsayılan Kayıt Ayarları", + "HeaderDateIssued": "Çıkış Tarihi", + "HeaderContinueListening": "Dinlemeye Devam Et", + "HeaderContainerProfileHelp": "Konteyner profilleri, belirli formatları oynatırken cihazın sınırlamalarını gösterir. Bir sınırlama uygulanırsa, format doğrudan oynatma için yapılandırılmış olsa bile ortam kodlanır.", + "HeaderContainerProfile": "Konteyner Profili", + "HeaderConnectionFailure": "Bağlantı hatası", + "HeaderConnectToServer": "Sunucuya bağlan", + "HeaderConfirmRevokeApiKey": "API Anahtarını İptal Et", + "HeaderConfirmProfileDeletion": "Profil Silme İşlemini Onayla", + "HeaderConfirmPluginInstallation": "Eklenti Yüklemesini Onayla", + "HeaderConfigureRemoteAccess": "Uzaktan Erişimi Yapılandırma", + "HeaderCodecProfileHelp": "Codec profilleri, belirli kodlayıcıları oynatırken cihazın sınırlamalarını gösterir. Eğer bir sınırlama uygulanırsa, kodeğin doğrudan oynaması için yapılandırılmış olsa bile, ortam kodlanır.", + "HeaderChapterImages": "Bölüm Görüntüleri", + "HeaderChannelAccess": "Kanal erişimi", + "HeaderCastCrew": "Kast ekibi", + "HeaderCastAndCrew": "Kast ekibi", + "HeaderCancelSeries": "Serileri İptal Et", + "HeaderCancelRecording": "Kaydı İptal Et", + "HeaderBranding": "dağlama", + "HeaderBooks": "Kitaplar", + "HeaderBlockItemsWithNoRating": "Tanınmayan veya bilinmeyen derecelendirme bilgisine sahip öğeleri engelle:", + "HeaderAudioSettings": "Ses ayarları", + "HeaderAudioBooks": "Sesli Kitaplar", + "HeaderAppearsOn": "Görünür", + "HeaderApp": "Uygulama", + "HeaderApiKeysHelp": "Jellyfin Server ile iletişim kurabilmek için harici uygulamaların bir API anahtarına sahip olmaları gerekir. Anahtarlar bir Jellyfin hesabıyla giriş yaparak veya uygulamaya manuel olarak bir anahtar vererek verilir.", + "HeaderApiKeys": "API Anahtarları", + "HeaderApiKey": "API Anahtarı", + "HeaderAllowMediaDeletionFrom": "Medyadan Silinmeye İzin Ver", + "HeaderAlert": "Alarm", + "HeaderAlbums": "Albümler", + "HeaderAdmin": "Yönetici", + "HeaderAdditionalParts": "İlave parçalar", + "HeaderAddUpdateImage": "Resim Ekle / Güncelle", + "HeaderAddToPlaylist": "Oynatma listesine ekle", + "HeaderAddToCollection": "Koleksiyona ekle", + "HeaderAddScheduledTaskTrigger": "Tetikleyici ekle", + "HeaderActivity": "Aktivite", + "HeaderActiveDevices": "Aktif Cihazlar", + "HeaderAccessScheduleHelp": "Belirli saatlerle erişimi sınırlamak için bir erişim programı oluşturun.", + "HeaderAccessSchedule": "Erişim Takvimi", + "HardwareAccelerationWarning": "Donanım ivmesini etkinleştirmek bazı ortamlarda dengesizliğe neden olabilir. İşletim sisteminizin ve video sürücülerinizin tamamen güncel olduğundan emin olun. Bunu etkinleştirdikten sonra video oynatmakta zorluk çekiyorsanız, ayarı tekrar Auto (Otomatik) olarak değiştirmeniz gerekecektir.", + "HandledByProxy": "Ters proxy tarafından kullanılır", + "HDPrograms": "HD programlar", + "H264EncodingPresetHelp": "Performansı artırmak için daha hızlı bir değer veya kaliteyi artırmak için daha yavaş bir değer seçin.", + "H264CrfHelp": "Sabit Hız Faktörü (CRF), x264 kodlayıcı için varsayılan kalite ayarıdır. Değerleri 0 ile 51 arasında ayarlayabilirsiniz, burada daha düşük değerler daha iyi kaliteyle sonuçlanır (daha yüksek dosya boyutları pahasına). Aklı başında değerleri 18 ila 28 arasındadır. X264 için varsayılan 23, bu nedenle bunu başlangıç noktası olarak kullanabilirsiniz.", + "GuideProviderSelectListings": "İlan Seç", + "GuideProviderLogin": "Oturum aç", + "Guide": "Rehber", + "GuestStar": "Konuk sanatçı", + "GroupVersions": "Grup versiyonları", + "GroupBySeries": "Seriye göre gruplandır", + "GenresValue": "Türler: {0}", + "GenreValue": "Tür: {0}", + "General": "Genel", + "Fullscreen": "Tam ekran", + "FormatValue": "Biçim: {0}", + "FolderTypeUnset": "Karışık içerik", + "Filters": "Filtreler", + "File": "Dosya", + "FetchingData": "Ek veri alınıyor", + "Features": "Özellikleri", + "Favorite": "Favori", + "FastForward": "İleri sar", + "FFmpegSavePathNotFound": "Girdiğiniz yolu kullanarak FFmpeg'i bulamıyoruz. FFprobe da gereklidir ve aynı klasörde bulunmalıdır. Bu bileşenler normalde aynı indirmede birlikte paketlenmiştir. Lütfen yolu kontrol edip tekrar deneyin.", + "Extras": "Ekstralar", + "ExtractChapterImagesHelp": "Bölüm görüntülerini çıkarmak, müşterilerin grafiksel sahne seçim menülerini görüntülemesini sağlar. İşlem yavaş olabilir, kaynak yoğun olabilir ve birkaç gigabaytlık alan gerektirebilir. Videolar keşfedildiğinde ve ayrıca zamanlanmış bir görev olarak çalışır. Zamanlanmış, zamanlanmış görevler alanında yapılandırılabilir. Bu görevi yoğun kullanım saatlerinde yapmanız önerilmez.", + "ExtraLarge": "Ekstra büyük", + "ExitFullscreen": "Tam ekrandan çık", + "EveryNDays": "Her {0} günde", + "ErrorSavingTvProvider": "TV sağlayıcısını kaydederken bir hata oluştu. Lütfen erişilebilir olduğundan emin olun ve tekrar deneyin.", + "ErrorPleaseSelectLineup": "Lütfen bir grup seçin ve tekrar deneyin. Hiç bir sıralama yoksa, lütfen kullanıcı adınızın, şifrenizin ve posta kodunuzun doğru olup olmadığını kontrol edin.", + "ErrorMessageStartHourGreaterThanEnd": "Bitiş saati, başlangıç saatinden büyük olmalıdır.", + "ErrorGettingTvLineups": "TV dizilimini indirirken bir hata oluştu. Lütfen bilgilerinizin doğru olduğundan emin olun ve tekrar deneyin.", + "ErrorDeletingItem": "Öğe Jellyfin Sunucusundan silinirken bir hata oluştu. Lütfen Jellyfin Server'ın medya klasörüne yazma erişimi olup olmadığını kontrol edin ve tekrar deneyin.", + "ErrorAddingXmlTvFile": "XmlTV dosyasına erişilirken bir hata oluştu. Lütfen dosyanın var olduğundan emin olun ve tekrar deneyin.", + "ErrorAddingTunerDevice": "Tuner cihazı eklenirken bir hata oluştu. Lütfen erişilebilir olduğundan emin olun ve tekrar deneyin.", + "ErrorAddingMediaPathToVirtualFolder": "Medya yolu eklenirken bir hata oluştu. Lütfen yolun geçerli olduğundan ve Jellyfin Server işleminin o konuma erişebildiğinden emin olun.", + "ErrorAddingListingsToSchedulesDirect": "Dizilişi Schedules Direct hesabınıza eklerken bir hata oluştu. Schedules Direct, hesap başına yalnızca sınırlı sayıda kadroya izin verir. Devam etmeden önce Schedules Direct web sitesine giriş yapmanız ve başka girişleri hesabınızdan kaldırmanız gerekebilir.", + "Episodes": "Bölümler", + "EndsAtValue": "{0} konumundaki biter", + "EnableThemeVideosHelp": "Kitaplığa göz atarken tema videoları arka planda oynatın.", + "EnableThemeVideos": "Tema videoları", + "EnableThemeSongsHelp": "Kitaplığa göz atarken tema şarkıları arka planda çalın.", + "EnableThemeSongs": "Tema şarkıları", + "EnableStreamLoopingHelp": "Canlı akışlar yalnızca birkaç saniye veri içeriyorsa ve sürekli istenmesi gerekiyorsa bunu etkinleştirin. Gerekmediğinde bunu etkinleştirmek sorunlara neden olabilir.", + "EnableStreamLooping": "Otomatik döngü canlı akışları" } diff --git a/webpack.common.js b/webpack.common.js index 26a38394cf..89b0089d88 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -1,5 +1,13 @@ const path = require("path"); +const { CleanWebpackPlugin} = require("clean-webpack-plugin"); const CopyPlugin = require("copy-webpack-plugin"); +const Assets = [ + "alameda/alameda.js", + "requirejs/require.js", + "libass-wasm/dist/subtitles-octopus-worker.js", + "libass-wasm/dist/subtitles-octopus-worker.data", + "libass-wasm/dist/subtitles-octopus-worker.wasm" +]; module.exports = { context: path.resolve(__dirname, "src"), @@ -10,15 +18,18 @@ module.exports = { ] }, plugins: [ - new CopyPlugin([ - { - from: "**/*", - to: "." - }, - { - context: path.resolve(__dirname), - from: "node_modules/libass-wasm/dist/subtitles-octopus-worker.*", - } - ]) + new CleanWebpackPlugin(), + new CopyPlugin([{ + from: "**/*", + to: "." + }]), + new CopyPlugin( + Assets.map(asset => { + return { + from: path.resolve(__dirname, `./node_modules/${asset}`), + to: path.resolve(__dirname, './dist/libraries') + }; + }) + ) ] };