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

Merge pull request #2224 from MediaBrowser/beta

Beta
This commit is contained in:
Luke 2016-10-12 15:43:28 -04:00 committed by GitHub
commit c9852fea56
734 changed files with 14033 additions and 38534 deletions

View file

@ -1,4 +1,4 @@
<div id="addPluginPage" data-role="page" class="page type-interior pluginConfigurationPage" data-helpurl="https://github.com/MediaBrowser/Wiki/wiki/Plugins" data-require="emby-select,emby-collapse,registrationservices,scripts/ratingdialog,scripts/addpluginpage"> <div id="addPluginPage" data-role="page" class="page type-interior pluginConfigurationPage" data-helpurl="https://github.com/MediaBrowser/Wiki/wiki/Plugins" data-require="emby-select,emby-collapse">
<div data-role="content"> <div data-role="content">
<div class="content-primary"> <div class="content-primary">
@ -27,7 +27,7 @@
<p id="btnInstallDiv" class="hide"> <p id="btnInstallDiv" class="hide">
<button is="emby-button" type="submit" id="btnInstall" class="raised button-submit block"> <button is="emby-button" type="submit" id="btnInstall" class="raised button-submit block">
<i class="md-icon">check</i><span>${Install}</span> <span>${Install}</span>
</button> </button>
</p> </p>
<p id="nonServerMsg"></p> <p id="nonServerMsg"></p>
@ -65,7 +65,6 @@
<input type="hidden" name="notify_url" value="https://mb3admin.com/admin/service/services/ppipn.php"> <input type="hidden" name="notify_url" value="https://mb3admin.com/admin/service/services/ppipn.php">
<input type="hidden" name="return" id="paypalReturnUrl" value="#"> <input type="hidden" name="return" id="paypalReturnUrl" value="#">
<button is="emby-button" type="submit" id="ppButton" class="raised block button-submit" style="background-color: #179BD7;color:#fff;"> <button is="emby-button" type="submit" id="ppButton" class="raised block button-submit" style="background-color: #179BD7;color:#fff;">
<i class="md-icon">check</i>
<span>${RegisterWithPayPal}</span> <span>${RegisterWithPayPal}</span>
</button> </button>
@ -78,14 +77,6 @@
</div> </div>
<br /> <br />
<div class="readOnlyContent"> <div class="readOnlyContent">
<div is="emby-collapse" title="${HeaderReviews}">
<div class="collapseContent">
<br />
<div id="ratingLine"></div>
<div id="latestReviews"></div>
</div>
</div>
<div is="emby-collapse" title="${HeaderDeveloperInfo}"> <div is="emby-collapse" title="${HeaderDeveloperInfo}">
<div class="collapseContent"> <div class="collapseContent">
<p id="developer"></p> <p id="developer"></p>

View file

@ -6,7 +6,6 @@
<p>${AutoOrganizeHelp}</p> <p>${AutoOrganizeHelp}</p>
<p>${AutoOrganizeTvHelp}</p>
<div> <div>
<label class="checkboxContainer"> <label class="checkboxContainer">
<input type="checkbox" is="emby-checkbox" id="chkEnableTvSorting" /> <input type="checkbox" is="emby-checkbox" id="chkEnableTvSorting" />
@ -19,7 +18,7 @@
<input is="emby-input" id="txtWatchFolder" type="text" label="${LabelWatchFolder}" /> <input is="emby-input" id="txtWatchFolder" type="text" label="${LabelWatchFolder}" />
<div class="fieldDescription">${LabelWatchFolderHelp}</div> <div class="fieldDescription">${LabelWatchFolderHelp}</div>
</div> </div>
<button type="button" is="emby-button" id="btnSelectWatchFolder" title="${ButtonSelectDirectory}" class="autoSize"><i class="md-icon">search</i></button> <button type="button" is="paper-icon-button-light" id="btnSelectWatchFolder" title="${ButtonSelectDirectory}" class="autoSize"><i class="md-icon">search</i></button>
</div> </div>
</div> </div>
<div class="inputContainer"> <div class="inputContainer">
@ -35,8 +34,6 @@
<div class="fieldDescription"></div> <div class="fieldDescription"></div>
</div> </div>
<br />
<div is="emby-collapse" title="${HeaderEpisodeFilePattern}"> <div is="emby-collapse" title="${HeaderEpisodeFilePattern}">
<div class="collapseContent"> <div class="collapseContent">
<br /> <br />
@ -157,7 +154,7 @@
<div class="fieldDescription checkboxFieldDescription">${LabelDeleteEmptyFoldersHelp}</div> <div class="fieldDescription checkboxFieldDescription">${LabelDeleteEmptyFoldersHelp}</div>
</div> </div>
<div> <div>
<button is="emby-button" type="submit" class="raised button-submit block"><i class="md-icon">check</i><span>${ButtonSave}</span></button> <button is="emby-button" type="submit" class="raised button-submit block"><span>${ButtonSave}</span></button>
</div> </div>
</form> </form>

View file

@ -0,0 +1,35 @@
{
"name": "document-register-element",
"description": "A stand-alone working lightweight version of the W3C Custom Elements specification",
"main": "./build/document-register-element.js",
"ignore": [
"test",
".jshintrc",
".travis.yml",
".TO_LOCALE.md",
".gitignore",
".gitmodules",
".npmignore",
"benchmark",
"dom4",
"ie8",
"src",
"template",
"package.json",
"index.html",
"testrhino.js",
"Makefile"
],
"homepage": "https://github.com/WebReflection/document-register-element",
"version": "0.5.4",
"_release": "0.5.4",
"_resolution": {
"type": "version",
"tag": "0.5.4",
"commit": "d1d0e80a1c8a0e3f9369280fca834e2cbac2ce6e"
},
"_source": "https://github.com/WebReflection/document-register-element.git",
"_target": "^0.5.4",
"_originalSource": "document-register-element",
"_direct": true
}

View file

@ -0,0 +1,19 @@
Copyright (C) 2014-2015 by WebReflection
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View file

@ -0,0 +1,9 @@
# A list of resources related to Custom Elements and this polyfill
## Demo
* [Self contained Custom Elements via restyle()](http://webreflection.blogspot.co.uk/2014/08/self-contained-custom-elements-via.html) post and its cross browser [demo](https://webreflection.github.io/custom-element/)
* [transform-3d](https://github.com/kentaromiura/transform-3d/) repo and [its demo](http://kentaromiura.github.io/transform-3d/)
* comparison against Polymer and demos in [Why Web Components Are Ready For Production](http://developer.telerik.com/featured/web-components-ready-production/)
* [W3C Specifications](http://w3c.github.io/webcomponents/spec/custom/)
* [HTML5 Rocks Article](http://www.html5rocks.com/en/tutorials/webcomponents/customelements/) except for the Shadow DOM being completely different specification

View file

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title>testing my-element</title>
<script src="build/document-register-element.js"></script>
<script src="test/my-element.js"></script>
</head>
<body>
<my-element>
some content
</my-element>
</body>

View file

@ -0,0 +1,23 @@
{
"name": "document-register-element",
"description": "A stand-alone working lightweight version of the W3C Custom Elements specification",
"main": "./build/document-register-element.js",
"ignore": [
"test",
".jshintrc",
".travis.yml",
".TO_LOCALE.md",
".gitignore",
".gitmodules",
".npmignore",
"benchmark",
"dom4",
"ie8",
"src",
"template",
"package.json",
"index.html",
"testrhino.js",
"Makefile"
]
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,52 @@
console.log('Loading: test.html');
var page = require('webpage').create();
var url = 'index.html';
page.open(url, function (status) {
if (status === 'success') {
setTimeout(function () {
var results = page.evaluate(function() {
// remove the first node with the total from the following counts
var passed = Math.max(0, document.querySelectorAll('.pass').length - 1);
return {
// retrieve the total executed tests number
total: ''.concat(
passed,
' blocks (',
document.querySelector('#wru strong').textContent.replace(/\D/g, ''),
' single tests)'
),
passed: passed,
failed: Math.max(0, document.querySelectorAll('.fail').length - 1),
failures: [].map.call(document.querySelectorAll('.fail'), function (node) {
return node.textContent;
}),
errored: Math.max(0, document.querySelectorAll('.error').length - 1),
errors: [].map.call(document.querySelectorAll('.error'), function (node) {
return node.textContent;
})
};
});
console.log('- - - - - - - - - -');
console.log('total: ' + results.total);
console.log('- - - - - - - - - -');
console.log('passed: ' + results.passed);
if (results.failed) {
console.log('failures: \n' + results.failures.join('\n'));
} else {
console.log('failed: ' + results.failed);
}
if (results.errored) {
console.log('errors: \n' + results.errors.join('\n'));
} else {
console.log('errored: ' + results.errored);
}
console.log('- - - - - - - - - -');
if (0 < results.failed + results.errored) {
status = 'failed';
}
phantom.exit(0);
}, 2000);
} else {
phantom.exit(1);
}
});

View file

@ -16,12 +16,12 @@
}, },
"devDependencies": {}, "devDependencies": {},
"ignore": [], "ignore": [],
"version": "1.1.79", "version": "1.1.87",
"_release": "1.1.79", "_release": "1.1.87",
"_resolution": { "_resolution": {
"type": "version", "type": "version",
"tag": "1.1.79", "tag": "1.1.87",
"commit": "bec0b71fec80821578400743ad836ce1a05c0c00" "commit": "21057764cdf82e9ef08514cca4e48c76d47e535f"
}, },
"_source": "https://github.com/MediaBrowser/Emby.ApiClient.Javascript.git", "_source": "https://github.com/MediaBrowser/Emby.ApiClient.Javascript.git",
"_target": "^1.1.51", "_target": "^1.1.51",

View file

@ -1,4 +1,5 @@
define(['events'], function (events) { define(['events'], function (events) {
'use strict';
/** /**
* Creates a new api client instance * Creates a new api client instance
@ -29,11 +30,11 @@
if (val != null) { if (val != null) {
if (val.toLowerCase().indexOf('http') != 0) { if (val.toLowerCase().indexOf('http') !== 0) {
throw new Error('Invalid url: ' + val); throw new Error('Invalid url: ' + val);
} }
var changed = val != serverAddress; var changed = val !== serverAddress;
serverAddress = val; serverAddress = val;
@ -189,7 +190,7 @@
var headers = request.headers || {}; var headers = request.headers || {};
if (request.dataType == 'json') { if (request.dataType === 'json') {
headers.accept = 'application/json'; headers.accept = 'application/json';
} }
@ -274,16 +275,16 @@
self.setRequestHeaders(request.headers); self.setRequestHeaders(request.headers);
} }
if (self.enableAutomaticNetworking === false || request.type != "GET") { if (self.enableAutomaticNetworking === false || request.type !== "GET") {
console.log('Requesting url without automatic networking: ' + request.url); console.log('Requesting url without automatic networking: ' + request.url);
return getFetchPromise(request).then(function (response) { return getFetchPromise(request).then(function (response) {
if (response.status < 400) { if (response.status < 400) {
if (request.dataType == 'json' || request.headers.accept == 'application/json') { if (request.dataType === 'json' || request.headers.accept === 'application/json') {
return response.json(); return response.json();
} else if (request.dataType == 'text' || (response.headers.get('Content-Type') || '').toLowerCase().indexOf('text/') == 0) { } else if (request.dataType === 'text' || (response.headers.get('Content-Type') || '').toLowerCase().indexOf('text/') === 0) {
return response.text(); return response.text();
} else { } else {
return response; return response;
@ -349,7 +350,7 @@
console.log("Attempting reconnection to " + url); console.log("Attempting reconnection to " + url);
var timeout = connectionMode == MediaBrowser.ConnectionMode.Local ? 7000 : 15000; var timeout = connectionMode === MediaBrowser.ConnectionMode.Local ? 7000 : 15000;
fetchWithTimeout(url + "/system/info/public", { fetchWithTimeout(url + "/system/info/public", {
@ -406,9 +407,9 @@
if (response.status < 400) { if (response.status < 400) {
if (request.dataType == 'json' || request.headers.accept == 'application/json') { if (request.dataType === 'json' || request.headers.accept === 'application/json') {
return response.json(); return response.json();
} else if (request.dataType == 'text' || (response.headers.get('Content-Type') || '').toLowerCase().indexOf('text/') == 0) { } else if (request.dataType === 'text' || (response.headers.get('Content-Type') || '').toLowerCase().indexOf('text/') === 0) {
return response.text(); return response.text();
} else { } else {
return response; return response;
@ -478,11 +479,11 @@
throw new Error("serverAddress is yet not set"); throw new Error("serverAddress is yet not set");
} }
var lowered = url.toLowerCase(); var lowered = url.toLowerCase();
if (lowered.indexOf('/emby') == -1 && lowered.indexOf('/mediabrowser') == -1) { if (lowered.indexOf('/emby') === -1 && lowered.indexOf('/mediabrowser') === -1) {
url += '/emby'; url += '/emby';
} }
if (name.charAt(0) != '/') { if (name.charAt(0) !== '/') {
url += '/'; url += '/';
} }
@ -535,7 +536,11 @@
return; return;
} }
self.openWebSocket(); try {
self.openWebSocket();
} catch (err) {
console.log("Error opening web socket: " + err);
}
}; };
function replaceAll(originalString, strReplace, strWith) { function replaceAll(originalString, strReplace, strWith) {
@ -598,7 +603,7 @@
else if (msg.MessageType === "UserUpdated" || msg.MessageType === "UserConfigurationUpdated") { else if (msg.MessageType === "UserUpdated" || msg.MessageType === "UserConfigurationUpdated") {
var user = msg.Data; var user = msg.Data;
if (user.Id == self.getCurrentUserId()) { if (user.Id === self.getCurrentUserId()) {
currentUser = null; currentUser = null;
} }
@ -670,13 +675,13 @@
return self.getDownloadSpeed(1000000).then(function (bitrate) { return self.getDownloadSpeed(1000000).then(function (bitrate) {
if (bitrate < 1000000) { if (bitrate < 1000000) {
return Math.round(bitrate * .8); return Math.round(bitrate * 0.8);
} else { } else {
// If that produced a fairly high speed, try again with a larger size to get a more accurate result // If that produced a fairly high speed, try again with a larger size to get a more accurate result
return self.getDownloadSpeed(2400000).then(function (bitrate) { return self.getDownloadSpeed(2400000).then(function (bitrate) {
return Math.round(bitrate * .8); return Math.round(bitrate * 0.8);
}); });
} }
@ -1735,7 +1740,7 @@
* Adds a virtual folder * Adds a virtual folder
* @param {String} name * @param {String} name
*/ */
self.addVirtualFolder = function (name, type, refreshLibrary, initialPaths, libraryOptions) { self.addVirtualFolder = function (name, type, refreshLibrary, libraryOptions) {
if (!name) { if (!name) {
throw new Error("null name"); throw new Error("null name");
@ -1758,7 +1763,6 @@
type: "POST", type: "POST",
url: url, url: url,
data: JSON.stringify({ data: JSON.stringify({
Paths: initialPaths,
LibraryOptions: libraryOptions LibraryOptions: libraryOptions
}), }),
contentType: 'application/json' contentType: 'application/json'
@ -1813,7 +1817,7 @@
* Adds an additional mediaPath to an existing virtual folder * Adds an additional mediaPath to an existing virtual folder
* @param {String} name * @param {String} name
*/ */
self.addMediaPath = function (virtualFolderName, mediaPath, refreshLibrary) { self.addMediaPath = function (virtualFolderName, mediaPath, networkSharePath, refreshLibrary) {
if (!virtualFolderName) { if (!virtualFolderName) {
throw new Error("null virtualFolderName"); throw new Error("null virtualFolderName");
@ -1825,15 +1829,50 @@
var url = "Library/VirtualFolders/Paths"; var url = "Library/VirtualFolders/Paths";
var pathInfo = {
Path: mediaPath
};
if (networkSharePath) {
pathInfo.NetworkPath = networkSharePath;
}
url = self.getUrl(url, { url = self.getUrl(url, {
refreshLibrary: refreshLibrary ? true : false, refreshLibrary: refreshLibrary ? true : false
path: mediaPath,
name: virtualFolderName
}); });
return self.ajax({ return self.ajax({
type: "POST", type: "POST",
url: url url: url,
data: JSON.stringify({
Name: virtualFolderName,
PathInfo: pathInfo
}),
contentType: 'application/json'
});
};
self.updateMediaPath = function (virtualFolderName, pathInfo) {
if (!virtualFolderName) {
throw new Error("null virtualFolderName");
}
if (!pathInfo) {
throw new Error("null pathInfo");
}
var url = "Library/VirtualFolders/Paths/Update";
url = self.getUrl(url);
return self.ajax({
type: "POST",
url: url,
data: JSON.stringify({
Name: virtualFolderName,
PathInfo: pathInfo
}),
contentType: 'application/json'
}); });
}; };
@ -2035,7 +2074,7 @@
throw new Error("File must be an image."); throw new Error("File must be an image.");
} }
if (file.type != "image/png" && file.type != "image/jpeg" && file.type != "image/jpeg") { if (file.type !== "image/png" && file.type !== "image/jpeg" && file.type !== "image/jpeg") {
throw new Error("File must be an image."); throw new Error("File must be an image.");
} }
@ -2092,7 +2131,7 @@
throw new Error("File must be an image."); throw new Error("File must be an image.");
} }
if (file.type != "image/png" && file.type != "image/jpeg" && file.type != "image/jpeg") { if (file.type !== "image/png" && file.type !== "image/jpeg" && file.type !== "image/jpeg") {
throw new Error("File must be an image."); throw new Error("File must be an image.");
} }
@ -2326,7 +2365,7 @@
}; };
self.getDefaultImageQuality = function (imageType) { self.getDefaultImageQuality = function (imageType) {
return imageType.toLowerCase() == 'backdrop' ? 80 : 90; return imageType.toLowerCase() === 'backdrop' ? 80 : 90;
}; };
function normalizeImageOptions(options) { function normalizeImageOptions(options) {
@ -2866,7 +2905,7 @@
var url; var url;
if ((typeof userId).toString().toLowerCase() == 'string') { if ((typeof userId).toString().toLowerCase() === 'string') {
url = self.getUrl("Users/" + userId + "/Items", options); url = self.getUrl("Users/" + userId + "/Items", options);
} else { } else {

View file

@ -1,4 +1,5 @@
define([], function () { define([], function () {
'use strict';
var myStore = {}; var myStore = {};
var cache; var cache;
@ -11,7 +12,7 @@
myStore.setItem = function (name, value) { myStore.setItem = function (name, value) {
if (localData) { if (localData) {
var changed = localData[name] != value; var changed = localData[name] !== value;
if (changed) { if (changed) {
localData[name] = value; localData[name] = value;

View file

@ -1,4 +1,5 @@
define([], function () { define([], function () {
'use strict';
var myStore = {}; var myStore = {};
var cache; var cache;
@ -12,7 +13,7 @@
localStorage.setItem(name, value); localStorage.setItem(name, value);
if (localData) { if (localData) {
var changed = localData[name] != value; var changed = localData[name] !== value;
if (changed) { if (changed) {
localData[name] = value; localData[name] = value;

View file

@ -1,21 +1,22 @@
define([], function () { define([], function () {
'use strict';
function myStore(defaultObject) { function MyStore(defaultObject) {
this.localData = {}; this.localData = {};
} }
myStore.prototype.setItem = function (name, value) { MyStore.prototype.setItem = function (name, value) {
this.localData[name] = value; this.localData[name] = value;
}; };
myStore.prototype.getItem = function (name) { MyStore.prototype.getItem = function (name) {
return this.localData[name]; return this.localData[name];
}; };
myStore.prototype.removeItem = function (name) { MyStore.prototype.removeItem = function (name) {
this.localData[name] = null; this.localData[name] = null;
}; };
return new myStore(); return new MyStore();
}); });

View file

@ -1,4 +1,5 @@
define(['events', 'apiclient', 'appStorage'], function (events, apiClientFactory, appStorage) { define(['events', 'apiclient', 'appStorage'], function (events, apiClientFactory, appStorage) {
'use strict';
var ConnectionState = { var ConnectionState = {
Unavailable: 0, Unavailable: 0,
@ -83,7 +84,7 @@
var headers = request.headers || {}; var headers = request.headers || {};
if (request.dataType == 'json') { if (request.dataType === 'json') {
headers.accept = 'application/json'; headers.accept = 'application/json';
} }
@ -177,7 +178,7 @@
if (response.status < 400) { if (response.status < 400) {
if (request.dataType == 'json' || request.headers.accept == 'application/json') { if (request.dataType === 'json' || request.headers.accept === 'application/json') {
return response.json(); return response.json();
} else { } else {
return response; return response;
@ -215,7 +216,7 @@
return connectUser; return connectUser;
}; };
var minServerVersion = '3.0.5972'; var minServerVersion = '3.0.5986';
self.minServerVersion = function (val) { self.minServerVersion = function (val) {
if (val) { if (val) {
@ -256,7 +257,7 @@
return servers.filter(function (s) { return servers.filter(function (s) {
return s.Id == id; return s.Id === id;
})[0]; })[0];
}; };
@ -402,7 +403,7 @@
var credentials = credentialProvider.credentials(); var credentials = credentialProvider.credentials();
var servers = credentials.Servers.filter(function (s) { var servers = credentials.Servers.filter(function (s) {
return s.Id == result.ServerId; return s.Id === result.ServerId;
}); });
var server = servers.length ? servers[0] : apiClient.serverInfo(); var server = servers.length ? servers[0] : apiClient.serverInfo();
@ -435,7 +436,7 @@
var info = { var info = {
Id: user.Id, Id: user.Id,
IsSignedInOffline: true IsSignedInOffline: true
} };
credentialProvider.addOrUpdateUser(server, info); credentialProvider.addOrUpdateUser(server, info);
} }
@ -448,12 +449,9 @@
} }
if (options.enableWebSocket !== false) { if (options.enableWebSocket !== false) {
if (!apiClient.isWebSocketOpenOrConnecting() && apiClient.isWebSocketSupported()) { console.log('calling apiClient.ensureWebSocket');
console.log('calling apiClient.openWebSocket'); apiClient.ensureWebSocket();
apiClient.openWebSocket();
}
} }
} }
@ -474,7 +472,7 @@
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
if (connectUser && connectUser.Id == credentials.ConnectUserId) { if (connectUser && connectUser.Id === credentials.ConnectUserId) {
resolve(); resolve();
} }
@ -537,12 +535,15 @@
url = getEmbyServerUrl(url, "Connect/Exchange?format=json&ConnectUserId=" + credentials.ConnectUserId); url = getEmbyServerUrl(url, "Connect/Exchange?format=json&ConnectUserId=" + credentials.ConnectUserId);
var auth = 'MediaBrowser Client="' + appName + '", Device="' + deviceName + '", DeviceId="' + deviceId + '", Version="' + appVersion + '"';
return ajax({ return ajax({
type: "GET", type: "GET",
url: url, url: url,
dataType: "json", dataType: "json",
headers: { headers: {
"X-MediaBrowser-Token": server.ExchangeToken "X-MediaBrowser-Token": server.ExchangeToken,
"X-Emby-Authorization": auth
} }
}).then(function (auth) { }).then(function (auth) {
@ -707,7 +708,7 @@
var credentials = credentialProvider.credentials(); var credentials = credentialProvider.credentials();
var servers = credentials.Servers.filter(function (u) { var servers = credentials.Servers.filter(function (u) {
return u.UserLinkType != "Guest"; return u.UserLinkType !== "Guest";
}); });
for (var j = 0, numServers = servers.length; j < numServers; j++) { for (var j = 0, numServers = servers.length; j < numServers; j++) {
@ -785,7 +786,7 @@
Name: i.Name, Name: i.Name,
RemoteAddress: i.Url, RemoteAddress: i.Url,
LocalAddress: i.LocalAddress, LocalAddress: i.LocalAddress,
UserLinkType: (i.UserType || '').toLowerCase() == "guest" ? "Guest" : "LinkedUser" UserLinkType: (i.UserType || '').toLowerCase() === "guest" ? "Guest" : "LinkedUser"
}; };
}); });
@ -849,7 +850,7 @@
return connectServers.filter(function (connectServer) { return connectServers.filter(function (connectServer) {
return server.Id == connectServer.Id; return server.Id === connectServer.Id;
}).length > 0; }).length > 0;
}); });
@ -924,11 +925,11 @@
console.log('Begin connectToServers, with ' + servers.length + ' servers'); console.log('Begin connectToServers, with ' + servers.length + ' servers');
if (servers.length == 1) { if (servers.length === 1) {
return self.connectToServer(servers[0], options).then(function (result) { return self.connectToServer(servers[0], options).then(function (result) {
if (result.State == ConnectionState.Unavailable) { if (result.State === ConnectionState.Unavailable) {
result.State = result.ConnectUser == null ? result.State = result.ConnectUser == null ?
ConnectionState.ConnectSignIn : ConnectionState.ConnectSignIn :
@ -945,7 +946,7 @@
if (firstServer) { if (firstServer) {
return self.connectToServer(firstServer, options).then(function (result) { return self.connectToServer(firstServer, options).then(function (result) {
if (result.State == ConnectionState.SignedIn) { if (result.State === ConnectionState.SignedIn) {
return result; return result;
@ -992,9 +993,9 @@
if (server.LastConnectionMode != null) { if (server.LastConnectionMode != null) {
//tests.push(server.LastConnectionMode); //tests.push(server.LastConnectionMode);
} }
if (tests.indexOf(ConnectionMode.Manual) == -1) { tests.push(ConnectionMode.Manual); } if (tests.indexOf(ConnectionMode.Manual) === -1) { tests.push(ConnectionMode.Manual); }
if (tests.indexOf(ConnectionMode.Local) == -1) { tests.push(ConnectionMode.Local); } if (tests.indexOf(ConnectionMode.Local) === -1) { tests.push(ConnectionMode.Local); }
if (tests.indexOf(ConnectionMode.Remote) == -1) { tests.push(ConnectionMode.Remote); } if (tests.indexOf(ConnectionMode.Remote) === -1) { tests.push(ConnectionMode.Remote); }
//beginWakeServer(server); //beginWakeServer(server);
@ -1007,7 +1008,7 @@
function stringEqualsIgnoreCase(str1, str2) { function stringEqualsIgnoreCase(str1, str2) {
return (str1 || '').toLowerCase() == (str2 || '').toLowerCase(); return (str1 || '').toLowerCase() === (str2 || '').toLowerCase();
} }
function compareVersions(a, b) { function compareVersions(a, b) {
@ -1049,7 +1050,7 @@
var skipTest = false; var skipTest = false;
var timeout = defaultTimeout; var timeout = defaultTimeout;
if (mode == ConnectionMode.Local) { if (mode === ConnectionMode.Local) {
enableRetry = true; enableRetry = true;
timeout = 8000; timeout = 8000;
@ -1060,7 +1061,7 @@
} }
} }
else if (mode == ConnectionMode.Manual) { else if (mode === ConnectionMode.Manual) {
if (stringEqualsIgnoreCase(address, server.LocalAddress)) { if (stringEqualsIgnoreCase(address, server.LocalAddress)) {
enableRetry = true; enableRetry = true;
@ -1078,7 +1079,7 @@
tryConnect(address, timeout).then(function (result) { tryConnect(address, timeout).then(function (result) {
if (compareVersions(self.minServerVersion(), result.Version) == 1) { if (compareVersions(self.minServerVersion(), result.Version) === 1) {
console.log('minServerVersion requirement not met. Server version: ' + result.Version); console.log('minServerVersion requirement not met. Server version: ' + result.Version);
resolve({ resolve({
@ -1086,6 +1087,11 @@
Servers: [server] Servers: [server]
}); });
} if (result.Id !== server.Id) {
// http request succeeded, but it's a different server than what was expected
testNextConnectionMode(tests, index + 1, server, options, resolve);
} else { } else {
console.log('calling onSuccessfulConnection with connection mode ' + mode + ' with server ' + server.Name); console.log('calling onSuccessfulConnection with connection mode ' + mode + ' with server ' + server.Name);
onSuccessfulConnection(server, result, mode, options, resolve); onSuccessfulConnection(server, result, mode, options, resolve);
@ -1178,7 +1184,7 @@
result.Servers.push(server); result.Servers.push(server);
result.ApiClient.updateServerInfo(server, connectionMode); result.ApiClient.updateServerInfo(server, connectionMode);
if (result.State == ConnectionState.SignedIn) { if (result.State === ConnectionState.SignedIn) {
afterConnected(result.ApiClient, options); afterConnected(result.ApiClient, options);
} }
@ -1197,7 +1203,7 @@
// attempt to correct bad input // attempt to correct bad input
address = address.trim(); address = address.trim();
if (address.toLowerCase().indexOf('http') != 0) { if (address.toLowerCase().indexOf('http') !== 0) {
address = "http://" + address; address = "http://" + address;
} }
@ -1314,7 +1320,7 @@
reject({ errorCode: 'passwordmatch' }); reject({ errorCode: 'passwordmatch' });
return; return;
} }
if (password != passwordConfirm) { if (password !== passwordConfirm) {
reject({ errorCode: 'passwordmatch' }); reject({ errorCode: 'passwordmatch' });
return; return;
} }
@ -1406,7 +1412,7 @@
var serverInfo = a.serverInfo(); var serverInfo = a.serverInfo();
// We have to keep this hack in here because of the addApiClient method // We have to keep this hack in here because of the addApiClient method
return !serverInfo || serverInfo.Id == item; return !serverInfo || serverInfo.Id === item;
})[0]; })[0];
}; };
@ -1443,7 +1449,7 @@
} }
var server = credentialProvider.credentials().Servers.filter(function (s) { var server = credentialProvider.credentials().Servers.filter(function (s) {
return s.Id == serverId; return s.Id === serverId;
}); });
server = server.length ? server[0] : null; server = server.length ? server[0] : null;
@ -1453,7 +1459,7 @@
var credentials = credentialProvider.credentials(); var credentials = credentialProvider.credentials();
credentials.Servers = credentials.Servers.filter(function (s) { credentials.Servers = credentials.Servers.filter(function (s) {
return s.Id != serverId; return s.Id !== serverId;
}); });
credentialProvider.credentials(credentials); credentialProvider.credentials(credentials);
@ -1560,7 +1566,7 @@
console.log('getRegistrationInfo has cached info'); console.log('getRegistrationInfo has cached info');
if (regInfo.deviceId == params.deviceId) { if (regInfo.deviceId === params.deviceId) {
console.log('getRegistrationInfo returning cached info'); console.log('getRegistrationInfo returning cached info');
return Promise.resolve(); return Promise.resolve();
} }
@ -1593,17 +1599,17 @@
var status = response.status; var status = response.status;
console.log('getRegistrationInfo response: ' + status); console.log('getRegistrationInfo response: ' + status);
if (status == 200) { if (status === 200) {
appStorage.setItem(cacheKey, JSON.stringify({ appStorage.setItem(cacheKey, JSON.stringify({
lastValidDate: new Date().getTime(), lastValidDate: new Date().getTime(),
deviceId: params.deviceId deviceId: params.deviceId
})); }));
return Promise.resolve(); return Promise.resolve();
} }
if (status == 401) { if (status === 401) {
return Promise.reject(); return Promise.reject();
} }
if (status == 403) { if (status === 403) {
return Promise.reject('overlimit'); return Promise.reject('overlimit');
} }

View file

@ -1,4 +1,5 @@
define(['events', 'appStorage'], function (events, appStorage) { define(['events', 'appStorage'], function (events, appStorage) {
'use strict';
return function (key) { return function (key) {
@ -57,7 +58,7 @@
} }
var existing = list.filter(function (s) { var existing = list.filter(function (s) {
return s.Id == server.Id; return s.Id === server.Id;
})[0]; })[0];
if (existing) { if (existing) {
@ -109,7 +110,7 @@
server.Users = server.Users || []; server.Users = server.Users || [];
var existing = server.Users.filter(function (s) { var existing = server.Users.filter(function (s) {
return s.Id == user.Id; return s.Id === user.Id;
})[0]; })[0];
if (existing) { if (existing) {

View file

@ -1,4 +1,5 @@
define([], function () { define([], function () {
'use strict';
function getCallbacks(obj, name) { function getCallbacks(obj, name) {
@ -32,7 +33,7 @@
var list = getCallbacks(obj, eventName); var list = getCallbacks(obj, eventName);
var i = list.indexOf(fn); var i = list.indexOf(fn);
if (i != -1) { if (i !== -1) {
list.splice(i, 1); list.splice(i, 1);
} }
}, },

View file

@ -1,4 +1,5 @@
define([], function () { define([], function () {
'use strict';
return function () { return function () {

View file

@ -1,4 +1,5 @@
define([], function () { define([], function () {
'use strict';
function getLocalMediaSource(serverId, itemId) { function getLocalMediaSource(serverId, itemId) {
return Promise.resolve(null); return Promise.resolve(null);

View file

@ -1,4 +1,5 @@
define([], function () { define([], function () {
'use strict';
function stringToArrayBuffer(string) { function stringToArrayBuffer(string) {
// UTF-16LE // UTF-16LE
@ -79,7 +80,7 @@
console.log(info); console.log(info);
if (info != null && info.socketId == socketId) { if (info != null && info.socketId === socketId) {
var json = arrayBufferToString(info.data); var json = arrayBufferToString(info.data);
console.log('Server discovery json: ' + json); console.log('Server discovery json: ' + json);
var server = JSON.parse(json); var server = JSON.parse(json);
@ -119,7 +120,7 @@
console.log('chrome.sockets.udp.bind'); console.log('chrome.sockets.udp.bind');
chrome.sockets.udp.bind(createInfo.socketId, '0.0.0.0', 0, function (bindResult) { chrome.sockets.udp.bind(createInfo.socketId, '0.0.0.0', 0, function (bindResult) {
if (getResultCode(bindResult) != 0) { if (getResultCode(bindResult) !== 0) {
console.log('bind fail: ' + bindResult); console.log('bind fail: ' + bindResult);
return; return;
} }
@ -130,7 +131,7 @@
chrome.sockets.udp.send(createInfo.socketId, data, '255.255.255.255', port, function (sendResult) { chrome.sockets.udp.send(createInfo.socketId, data, '255.255.255.255', port, function (sendResult) {
if (getResultCode(sendResult) != 0) { if (getResultCode(sendResult) !== 0) {
console.log('send fail: ' + sendResult); console.log('send fail: ' + sendResult);
} else { } else {

View file

@ -1,4 +1,5 @@
define([], function () { define([], function () {
'use strict';
function listenerSession(resolve, timeoutMs) { function listenerSession(resolve, timeoutMs) {
@ -78,7 +79,7 @@
var stringLength = eventArguments.getDataReader().unconsumedBufferLength; var stringLength = eventArguments.getDataReader().unconsumedBufferLength;
var receivedMessage = eventArguments.getDataReader().readString(stringLength); var receivedMessage = eventArguments.getDataReader().readString(stringLength);
if (receivedMessage == stringToSend) { if (receivedMessage === stringToSend) {
return; return;
} }
@ -97,7 +98,7 @@
servers.push(server); servers.push(server);
} catch (exception) { } catch (exception) {
onError("Error receiving message: " + receivedMessage); onError("Error receiving message: " + exception);
} }
} }

View file

@ -1,4 +1,5 @@
define([], function () { define([], function () {
'use strict';
return { return {

View file

@ -1,4 +1,5 @@
define(['localassetmanager'], function (localAssetManager) { define(['localassetmanager'], function (localAssetManager) {
'use strict';
return function (connectionManager) { return function (connectionManager) {
@ -43,9 +44,9 @@
return uploadHistory.FilesUploaded.filter(function (u) { return uploadHistory.FilesUploaded.filter(function (u) {
return getUploadId(file) == u.Id; return getUploadId(file) === u.Id;
}).length == 0; }).length === 0;
}); });
} }

View file

@ -1,4 +1,5 @@
define(['localassetmanager'], function (LocalAssetManager) { define(['localassetmanager'], function (LocalAssetManager) {
'use strict';
return function () { return function () {
@ -248,55 +249,54 @@
// Just for now while media syncing gets worked out // Just for now while media syncing gets worked out
deferred.resolve(); deferred.resolve();
return;
var libraryItem = localItem.Item; //var libraryItem = localItem.Item;
var serverId = libraryItem.ServerId; //var serverId = libraryItem.ServerId;
var itemId = null; //var itemId = null;
var imageTag = null; //var imageTag = null;
var imageType = "Primary"; //var imageType = "Primary";
switch (index) { //switch (index) {
case 0: // case 0:
itemId = libraryItem.Id; // itemId = libraryItem.Id;
imageType = "Primary"; // imageType = "Primary";
imageTag = (libraryItem.ImageTags || {})["Primary"]; // imageTag = (libraryItem.ImageTags || {})["Primary"];
break; // break;
case 1: // case 1:
itemId = libraryItem.SeriesId; // itemId = libraryItem.SeriesId;
imageType = "Primary"; // imageType = "Primary";
imageTag = libraryItem.SeriesPrimaryImageTag; // imageTag = libraryItem.SeriesPrimaryImageTag;
break; // break;
case 2: // case 2:
itemId = libraryItem.SeriesId; // itemId = libraryItem.SeriesId;
imageType = "Thumb"; // imageType = "Thumb";
imageTag = libraryItem.SeriesPrimaryImageTag; // imageTag = libraryItem.SeriesPrimaryImageTag;
break; // break;
case 3: // case 3:
itemId = libraryItem.AlbumId; // itemId = libraryItem.AlbumId;
imageType = "Primary"; // imageType = "Primary";
imageTag = libraryItem.AlbumPrimaryImageTag; // imageTag = libraryItem.AlbumPrimaryImageTag;
break; // break;
default: // default:
break; // break;
} //}
if (!itemId || !imageTag) { //if (!itemId || !imageTag) {
getNextImage(index + 1, apiClient, localItem, deferred); // getNextImage(index + 1, apiClient, localItem, deferred);
return; // return;
} //}
downloadImage(apiClient, serverId, itemId, imageTag, imageType).then(function () { //downloadImage(apiClient, serverId, itemId, imageTag, imageType).then(function () {
// For the sake of simplicity, limit to one image // // For the sake of simplicity, limit to one image
deferred.resolve(); // deferred.resolve();
return; // return;
getNextImage(index + 1, apiClient, localItem, deferred); // getNextImage(index + 1, apiClient, localItem, deferred);
}, getOnFail(deferred)); //}, getOnFail(deferred));
} }
function downloadImage(apiClient, serverId, itemId, imageTag, imageType) { function downloadImage(apiClient, serverId, itemId, imageTag, imageType) {
@ -340,7 +340,7 @@
} }
var files = jobItem.AdditionalFiles.filter(function (f) { var files = jobItem.AdditionalFiles.filter(function (f) {
return f.Type == 'Subtitles'; return f.Type === 'Subtitles';
}); });
var mediaSource = jobItem.Item.MediaSources[0]; var mediaSource = jobItem.Item.MediaSources[0];
@ -375,7 +375,7 @@
var deferred = DeferredBuilder.Deferred(); var deferred = DeferredBuilder.Deferred();
var subtitleStream = mediaSource.MediaStreams.filter(function (m) { var subtitleStream = mediaSource.MediaStreams.filter(function (m) {
return m.Type == 'Subtitle' && m.Index == file.Index; return m.Type === 'Subtitle' && m.Index === file.Index;
})[0]; })[0];
if (!subtitleStream) { if (!subtitleStream) {
@ -445,7 +445,7 @@
var userIdsWithAccess = syncDataResult.ItemUserAccess[itemId]; var userIdsWithAccess = syncDataResult.ItemUserAccess[itemId];
if (userIdsWithAccess.join(',') == savedUserIdsWithAccess.join(',')) { if (userIdsWithAccess.join(',') === savedUserIdsWithAccess.join(',')) {
// Hasn't changed, nothing to do // Hasn't changed, nothing to do
deferred.resolve(); deferred.resolve();
} }

View file

@ -1,4 +1,5 @@
define(['serversync'], function (ServerSync) { define(['serversync'], function (ServerSync) {
'use strict';
function syncNext(connectionManager, servers, index, options, resolve, reject) { function syncNext(connectionManager, servers, index, options, resolve, reject) {

View file

@ -1,4 +1,5 @@
define(['localassetmanager'], function (localAssetManager) { define(['localassetmanager'], function (localAssetManager) {
'use strict';
function syncNext(users, index, resolve, reject, apiClient, server) { function syncNext(users, index, resolve, reject, apiClient, server) {

View file

@ -1,4 +1,5 @@
define([], function () { define([], function () {
'use strict';
return function (connectionManager) { return function (connectionManager) {
@ -20,7 +21,7 @@
return connectionManager.connectToServer(server, connectionOptions).then(function (result) { return connectionManager.connectToServer(server, connectionOptions).then(function (result) {
if (result.State == MediaBrowser.ConnectionState.SignedIn) { if (result.State === MediaBrowser.ConnectionState.SignedIn) {
return performSync(server, options); return performSync(server, options);
} else { } else {
console.log('Unable to connect to server id: ' + server.Id); console.log('Unable to connect to server id: ' + server.Id);
@ -42,7 +43,7 @@
var uploadPhotos = options.uploadPhotos !== false; var uploadPhotos = options.uploadPhotos !== false;
if (options.cameraUploadServers && options.cameraUploadServers.indexOf(server.Id) == -1) { if (options.cameraUploadServers && options.cameraUploadServers.indexOf(server.Id) === -1) {
uploadPhotos = false; uploadPhotos = false;
} }

View file

@ -1,4 +1,5 @@
define([], function () { define([], function () {
'use strict';
function send(info) { function send(info) {

View file

@ -14,12 +14,12 @@
}, },
"devDependencies": {}, "devDependencies": {},
"ignore": [], "ignore": [],
"version": "1.4.236", "version": "1.4.299",
"_release": "1.4.236", "_release": "1.4.299",
"_resolution": { "_resolution": {
"type": "version", "type": "version",
"tag": "1.4.236", "tag": "1.4.299",
"commit": "d369818012719cb7fd38b052073428631937ae6f" "commit": "7e708cf27aa74f7f0d0aaa30d95d3e1f09b71ce3"
}, },
"_source": "https://github.com/MediaBrowser/emby-webcomponents.git", "_source": "https://github.com/MediaBrowser/emby-webcomponents.git",
"_target": "^1.2.1", "_target": "^1.2.1",

View file

@ -4,10 +4,21 @@
padding: 0; padding: 0;
border: none; border: none;
max-height: 84%; max-height: 84%;
border-radius: 1px !important;
color: #fff;
}
.actionsheet-not-fullscreen {
background-color: #2a2a2a;
}
.actionSheetMenuItem:hover {
background-color: #333;
} }
.actionsheet-fullscreen { .actionsheet-fullscreen {
max-height: none; max-height: none;
border-radius: 0 !important;
} }
.actionSheetContent-centered { .actionSheetContent-centered {
@ -35,6 +46,8 @@
font-weight: inherit; font-weight: inherit;
align-items: center; align-items: center;
flex-shrink: 0; flex-shrink: 0;
background: transparent;
box-shadow: none;
} }
.actionSheetMenuItem-noflex { .actionSheetMenuItem-noflex {
@ -94,4 +107,4 @@
position: fixed; position: fixed;
top: .75em; top: .75em;
left: .5em; left: .5em;
} }

View file

@ -1,4 +1,5 @@
define(['dialogHelper', 'layoutManager', 'globalize', 'browser', 'dom', 'emby-button', 'css!./actionsheet', 'material-icons', 'scrollStyles'], function (dialogHelper, layoutManager, globalize, browser, dom) { define(['dialogHelper', 'layoutManager', 'globalize', 'browser', 'dom', 'emby-button', 'css!./actionsheet', 'material-icons', 'scrollStyles'], function (dialogHelper, layoutManager, globalize, browser, dom) {
'use strict';
function getOffsets(elems) { function getOffsets(elems) {
@ -25,7 +26,9 @@
results[i] = { results[i] = {
top: box.top, top: box.top,
left: box.left left: box.left,
width: box.width,
height: box.height
}; };
} }
@ -44,11 +47,11 @@
var pos = getOffsets([options.positionTo])[0]; var pos = getOffsets([options.positionTo])[0];
if (options.positionY != 'top') { if (options.positionY !== 'top') {
pos.top += options.positionTo.offsetHeight / 2; pos.top += (pos.height || 0) / 2;
} }
pos.left += options.positionTo.offsetWidth / 2; pos.left += (pos.width || 0) / 2;
var height = dlg.offsetHeight || 300; var height = dlg.offsetHeight || 300;
var width = dlg.offsetWidth || 160; var width = dlg.offsetWidth || 160;
@ -119,6 +122,8 @@
if (isFullscreen) { if (isFullscreen) {
dlg.classList.add('actionsheet-fullscreen'); dlg.classList.add('actionsheet-fullscreen');
} else {
dlg.classList.add('actionsheet-not-fullscreen');
} }
var extraSpacing = !layoutManager.tv; var extraSpacing = !layoutManager.tv;

View file

@ -1,4 +1,5 @@
define(['dialog', 'globalize'], function (dialog, globalize) { define(['dialog', 'globalize'], function (dialog, globalize) {
'use strict';
return function (text, title) { return function (text, title) {
@ -15,7 +16,7 @@ define(['dialog', 'globalize'], function (dialog, globalize) {
var items = []; var items = [];
items.push({ items.push({
name: globalize.translate('sharedcomponents#ButtonOk'), name: globalize.translate('sharedcomponents#ButtonGotIt'),
id: 'ok', id: 'ok',
type: 'submit' type: 'submit'
}); });
@ -23,7 +24,7 @@ define(['dialog', 'globalize'], function (dialog, globalize) {
options.buttons = items; options.buttons = items;
return dialog(options).then(function (result) { return dialog(options).then(function (result) {
if (result == 'ok') { if (result === 'ok') {
return Promise.resolve(); return Promise.resolve();
} }

View file

@ -1,4 +1,5 @@
define([], function () { define([], function () {
'use strict';
function replaceAll(str, find, replace) { function replaceAll(str, find, replace) {

View file

@ -1,14 +1,16 @@
define(['focusManager', 'css!./style.css', 'paper-icon-button-light', 'material-icons'], function (focusManager) { define(['focusManager', 'css!./style.css', 'paper-icon-button-light', 'material-icons'], function (focusManager) {
'use strict';
var selectedButtonClass = 'alphaPickerButton-selected'; var selectedButtonClass = 'alphaPickerButton-selected';
function focus() { function focus() {
var selected = this.querySelector('.' + selectedButtonClass); var scope = this;
var selected = scope.querySelector('.' + selectedButtonClass);
if (selected) { if (selected) {
focusManager.focus(selected); focusManager.focus(selected);
} else { } else {
focusManager.autoFocus(this, true); focusManager.autoFocus(scope, true);
} }
} }
@ -25,11 +27,9 @@ define(['focusManager', 'css!./style.css', 'paper-icon-button-light', 'material-
var letters; var letters;
html += '<div class="alphaPickerRow">'; html += '<div class="alphaPickerRow">';
if (options.mode == 'keyboard') { if (options.mode === 'keyboard') {
// space_bar icon // space_bar icon
html += '<button data-value=" " is="paper-icon-button-light" class="alphaPickerButton autoSize">\ html += '<button data-value=" " is="paper-icon-button-light" class="alphaPickerButton autoSize"><i class="md-icon alphaPickerButtonIcon">&#xE256;</i></button>';
<i class="md-icon alphaPickerButtonIcon">&#xE256;</i>\
</button>';
} else { } else {
letters = ['#']; letters = ['#'];
html += letters.map(getLetterButton).join(''); html += letters.map(getLetterButton).join('');
@ -38,11 +38,9 @@ define(['focusManager', 'css!./style.css', 'paper-icon-button-light', 'material-
letters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']; letters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
html += letters.map(getLetterButton).join(''); html += letters.map(getLetterButton).join('');
if (options.mode == 'keyboard') { if (options.mode === 'keyboard') {
// backspace icon // backspace icon
html += '<button data-value="backspace" is="paper-icon-button-light" class="alphaPickerButton autoSize">\ html += '<button data-value="backspace" is="paper-icon-button-light" class="alphaPickerButton autoSize"><i class="md-icon alphaPickerButtonIcon">&#xE14A;</i></button>';
<i class="md-icon alphaPickerButtonIcon">&#xE14A;</i>\
</button>';
html += '</div>'; html += '</div>';
letters = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']; letters = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
@ -60,7 +58,7 @@ define(['focusManager', 'css!./style.css', 'paper-icon-button-light', 'material-
element.focus = focus; element.focus = focus;
} }
function alphaPicker(options) { function AlphaPicker(options) {
var self = this; var self = this;
@ -83,7 +81,7 @@ define(['focusManager', 'css!./style.css', 'paper-icon-button-light', 'material-
alphaFocusTimeout = null; alphaFocusTimeout = null;
if (document.activeElement == alphaFocusedElement) { if (document.activeElement === alphaFocusedElement) {
var value = alphaFocusedElement.getAttribute('data-value'); var value = alphaFocusedElement.getAttribute('data-value');
self.value(value, true); self.value(value, true);
} }
@ -125,7 +123,7 @@ define(['focusManager', 'css!./style.css', 'paper-icon-button-light', 'material-
if (alphaPickerButton) { if (alphaPickerButton) {
var value = alphaPickerButton.getAttribute('data-value'); var value = alphaPickerButton.getAttribute('data-value');
if (currentValue == value.toUpperCase()) { if (currentValue === value.toUpperCase()) {
self.value(null, true); self.value(null, true);
} else { } else {
self.value(value, true); self.value(value, true);
@ -173,7 +171,7 @@ define(['focusManager', 'css!./style.css', 'paper-icon-button-light', 'material-
itemsContainer.addEventListener('focus', onItemsFocusIn, true); itemsContainer.addEventListener('focus', onItemsFocusIn, true);
} }
if (options.mode == 'keyboard') { if (options.mode === 'keyboard') {
element.addEventListener('click', onAlphaPickerInKeyboardModeClick); element.addEventListener('click', onAlphaPickerInKeyboardModeClick);
} }
@ -225,14 +223,14 @@ define(['focusManager', 'css!./style.css', 'paper-icon-button-light', 'material-
value = value.toUpperCase(); value = value.toUpperCase();
currentValue = value; currentValue = value;
if (options.mode != 'keyboard') { if (options.mode !== 'keyboard') {
selected = element.querySelector('.' + selectedButtonClass); selected = element.querySelector('.' + selectedButtonClass);
btn = element.querySelector('.alphaPickerButton[data-value=\'' + value + '\']'); btn = element.querySelector('.alphaPickerButton[data-value=\'' + value + '\']');
if (btn && btn != selected) { if (btn && btn !== selected) {
btn.classList.add(selectedButtonClass); btn.classList.add(selectedButtonClass);
} }
if (selected && selected != btn) { if (selected && selected !== btn) {
selected.classList.remove(selectedButtonClass); selected.classList.remove(selectedButtonClass);
} }
} }
@ -281,5 +279,5 @@ define(['focusManager', 'css!./style.css', 'paper-icon-button-light', 'material-
self.visible(true); self.visible(true);
} }
return alphaPicker; return AlphaPicker;
}); });

View file

@ -1,4 +1,5 @@
define(['appStorage', 'events'], function (appStorage, events) { define(['appStorage', 'events'], function (appStorage, events) {
'use strict';
function getKey(name, userId) { function getKey(name, userId) {
@ -9,7 +10,7 @@ define(['appStorage', 'events'], function (appStorage, events) {
return name; return name;
} }
return new function () { function AppSettings() {
var self = this; var self = this;
@ -19,7 +20,7 @@ define(['appStorage', 'events'], function (appStorage, events) {
self.set('enableAutoLogin', val.toString()); self.set('enableAutoLogin', val.toString());
} }
return self.get('enableAutoLogin') != 'false'; return self.get('enableAutoLogin') !== 'false';
}; };
self.enableAutomaticBitrateDetection = function (val) { self.enableAutomaticBitrateDetection = function (val) {
@ -28,7 +29,7 @@ define(['appStorage', 'events'], function (appStorage, events) {
self.set('enableAutomaticBitrateDetection', val.toString()); self.set('enableAutomaticBitrateDetection', val.toString());
} }
return self.get('enableAutomaticBitrateDetection') != 'false'; return self.get('enableAutomaticBitrateDetection') !== 'false';
}; };
self.maxStreamingBitrate = function (val) { self.maxStreamingBitrate = function (val) {
@ -66,7 +67,7 @@ define(['appStorage', 'events'], function (appStorage, events) {
self.set('syncOnlyOnWifi', val.toString()); self.set('syncOnlyOnWifi', val.toString());
} }
return self.get('syncOnlyOnWifi') != 'false'; return self.get('syncOnlyOnWifi') !== 'false';
}; };
self.syncPath = function (val) { self.syncPath = function (val) {
@ -99,7 +100,7 @@ define(['appStorage', 'events'], function (appStorage, events) {
appStorage.setItem(getKey(name, userId), value); appStorage.setItem(getKey(name, userId), value);
if (currentValue != value) { if (currentValue !== value) {
events.trigger(self, 'change', [name]); events.trigger(self, 'change', [name]);
} }
}; };
@ -108,5 +109,7 @@ define(['appStorage', 'events'], function (appStorage, events) {
return appStorage.getItem(getKey(name, userId)); return appStorage.getItem(getKey(name, userId));
}; };
}(); }
return new AppSettings();
}); });

View file

@ -1,4 +1,5 @@
define(['browser', 'connectionManager', 'playbackManager', 'dom', 'css!./style'], function (browser, connectionManager, playbackManager, dom) { define(['browser', 'connectionManager', 'playbackManager', 'dom', 'css!./style'], function (browser, connectionManager, playbackManager, dom) {
'use strict';
function enableAnimation(elem) { function enableAnimation(elem) {
@ -18,7 +19,7 @@
return true; return true;
} }
function backdrop() { function Backdrop() {
var self = this; var self = this;
var isDestroyed; var isDestroyed;
@ -52,7 +53,7 @@
currentAnimation = animation; currentAnimation = animation;
animation.onfinish = function () { animation.onfinish = function () {
if (animation == currentAnimation) { if (animation === currentAnimation) {
currentAnimation = null; currentAnimation = null;
} }
if (existingBackdropImage && existingBackdropImage.parentNode) { if (existingBackdropImage && existingBackdropImage.parentNode) {
@ -166,14 +167,14 @@
var elem = getBackdropContainer(); var elem = getBackdropContainer();
var existingBackdropImage = elem.querySelector('.displayingBackdropImage'); var existingBackdropImage = elem.querySelector('.displayingBackdropImage');
if (existingBackdropImage && existingBackdropImage.getAttribute('data-url') == url) { if (existingBackdropImage && existingBackdropImage.getAttribute('data-url') === url) {
if (existingBackdropImage.getAttribute('data-url') == url) { if (existingBackdropImage.getAttribute('data-url') === url) {
return; return;
} }
existingBackdropImage.classList.remove('displayingBackdropImage'); existingBackdropImage.classList.remove('displayingBackdropImage');
} }
var instance = new backdrop(); var instance = new Backdrop();
instance.load(url, elem, existingBackdropImage); instance.load(url, elem, existingBackdropImage);
currentLoadingBackdrop = instance; currentLoadingBackdrop = instance;
} }
@ -215,28 +216,38 @@
var list = []; var list = [];
var onImg = function (img) {
list.push(img);
};
for (var i = 0, length = items.length; i < length; i++) { for (var i = 0, length = items.length; i < length; i++) {
var itemImages = getItemImageUrls(items[i]); var itemImages = getItemImageUrls(items[i]);
itemImages.forEach(function (img) { itemImages.forEach(onImg);
list.push(img);
});
} }
return list; return list;
} }
function arraysEqual(a, b) { function arraysEqual(a, b) {
if (a === b) return true; if (a === b) {
if (a == null || b == null) return false; return true;
if (a.length != b.length) return false; }
if (a == null || b == null) {
return false;
}
if (a.length !== b.length) {
return false;
}
// If you don't care about the order of the elements inside // If you don't care about the order of the elements inside
// the array, you should sort both arrays here. // the array, you should sort both arrays here.
for (var i = 0; i < a.length; ++i) { for (var i = 0; i < a.length; ++i) {
if (a[i] !== b[i]) return false; if (a[i] !== b[i]) {
return false;
}
} }
return true; return true;
} }

View file

@ -1,27 +1,28 @@
define([], function () { define([], function () {
'use strict';
function isTv() { function isTv() {
// This is going to be really difficult to get right // This is going to be really difficult to get right
var userAgent = navigator.userAgent.toLowerCase(); var userAgent = navigator.userAgent.toLowerCase();
if (userAgent.indexOf('tv') != -1) { if (userAgent.indexOf('tv') !== -1) {
return true; return true;
} }
if (userAgent.indexOf('samsungbrowser') != -1) { if (userAgent.indexOf('samsungbrowser') !== -1) {
return true; return true;
} }
if (userAgent.indexOf('nintendo') != -1) { if (userAgent.indexOf('nintendo') !== -1) {
return true; return true;
} }
if (userAgent.indexOf('viera') != -1) { if (userAgent.indexOf('viera') !== -1) {
return true; return true;
} }
if (userAgent.indexOf('webos') != -1) { if (userAgent.indexOf('webos') !== -1) {
return true; return true;
} }
@ -45,7 +46,7 @@
var lower = userAgent.toLowerCase(); var lower = userAgent.toLowerCase();
for (var i = 0, length = terms.length; i < length; i++) { for (var i = 0, length = terms.length; i < length; i++) {
if (lower.indexOf(terms[i]) != -1) { if (lower.indexOf(terms[i]) !== -1) {
return true; return true;
} }
} }
@ -87,6 +88,34 @@
} }
} }
function hasKeyboard(browser) {
if (browser.touch) {
return true;
}
if (browser.xboxOne) {
return true;
}
if (browser.ps4) {
return true;
}
if (browser.edgeUwp) {
// This is OK for now, but this won't always be true
// Should we use this?
// https://gist.github.com/wagonli/40d8a31bd0d6f0dd7a5d
return true;
}
if (browser.tv) {
return true;
}
return false;
}
var uaMatch = function (ua) { var uaMatch = function (ua) {
ua = ua.toLowerCase(); ua = ua.toLowerCase();
@ -100,6 +129,8 @@
ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
[]; [];
var versionMatch = /(version)[ \/]([\w.]+)/.exec(ua);
var platform_match = /(ipad)/.exec(ua) || var platform_match = /(ipad)/.exec(ua) ||
/(iphone)/.exec(ua) || /(iphone)/.exec(ua) ||
/(android)/.exec(ua) || /(android)/.exec(ua) ||
@ -107,27 +138,41 @@
var browser = match[1] || ""; var browser = match[1] || "";
if (browser == "edge") { if (browser === "edge") {
platform_match = [""]; platform_match = [""];
} else { } else {
if (ua.indexOf("windows phone") != -1 || ua.indexOf("iemobile") != -1) { if (ua.indexOf("windows phone") !== -1 || ua.indexOf("iemobile") !== -1) {
// http://www.neowin.net/news/ie11-fakes-user-agent-to-fool-gmail-in-windows-phone-81-gdr1-update // http://www.neowin.net/news/ie11-fakes-user-agent-to-fool-gmail-in-windows-phone-81-gdr1-update
browser = "msie"; browser = "msie";
} }
else if (ua.indexOf("like gecko") != -1 && ua.indexOf('webkit') == -1 && ua.indexOf('opera') == -1 && ua.indexOf('chrome') == -1 && ua.indexOf('safari') == -1) { else if (ua.indexOf("like gecko") !== -1 && ua.indexOf('webkit') === -1 && ua.indexOf('opera') === -1 && ua.indexOf('chrome') === -1 && ua.indexOf('safari') === -1) {
browser = "msie"; browser = "msie";
} }
} }
if (browser == 'opr') { if (browser === 'opr') {
browser = 'opera'; browser = 'opera';
} }
var version;
if (versionMatch && versionMatch.length > 2) {
version = versionMatch[2];
}
version = version || match[2] || "0";
var versionMajor = parseInt(version.split('.')[0]);
if (isNaN(versionMajor)) {
versionMajor = 0;
}
return { return {
browser: browser, browser: browser,
version: match[2] || "0", version: version,
platform: platform_match[0] || "" platform: platform_match[0] || "",
versionMajor: versionMajor
}; };
}; };
@ -138,17 +183,18 @@
if (matched.browser) { if (matched.browser) {
browser[matched.browser] = true; browser[matched.browser] = true;
browser.version = matched.version; browser.version = matched.version;
browser.versionMajor = matched.versionMajor;
} }
if (matched.platform) { if (matched.platform) {
browser[matched.platform] = true; browser[matched.platform] = true;
} }
if (!browser.chrome && !browser.msie && !browser.edge && !browser.opera && userAgent.toLowerCase().indexOf("webkit") != -1) { if (!browser.chrome && !browser.msie && !browser.edge && !browser.opera && userAgent.toLowerCase().indexOf("webkit") !== -1) {
browser.safari = true; browser.safari = true;
} }
if (userAgent.toLowerCase().indexOf("playstation 4") != -1) { if (userAgent.toLowerCase().indexOf("playstation 4") !== -1) {
browser.ps4 = true; browser.ps4 = true;
browser.tv = true; browser.tv = true;
} }
@ -157,14 +203,14 @@
browser.mobile = true; browser.mobile = true;
} }
browser.xboxOne = userAgent.toLowerCase().indexOf('xbox') != -1; browser.xboxOne = userAgent.toLowerCase().indexOf('xbox') !== -1;
browser.animate = document.documentElement.animate != null; browser.animate = document.documentElement.animate != null;
browser.tizen = userAgent.toLowerCase().indexOf('tizen') != -1 || userAgent.toLowerCase().indexOf('smarthub') != -1; browser.tizen = userAgent.toLowerCase().indexOf('tizen') !== -1 || userAgent.toLowerCase().indexOf('smarthub') !== -1;
browser.web0s = userAgent.toLowerCase().indexOf('Web0S'.toLowerCase()) != -1; browser.web0s = userAgent.toLowerCase().indexOf('Web0S'.toLowerCase()) !== -1;
browser.edgeUwp = browser.edge && userAgent.toLowerCase().indexOf('msapphost') != -1; browser.edgeUwp = browser.edge && userAgent.toLowerCase().indexOf('msapphost') !== -1;
browser.tv = isTv(); browser.tv = isTv();
browser.operaTv = browser.tv && userAgent.toLowerCase().indexOf('opr/') != -1; browser.operaTv = browser.tv && userAgent.toLowerCase().indexOf('opr/') !== -1;
if (!isStyleSupported('display', 'flex')) { if (!isStyleSupported('display', 'flex')) {
browser.noFlex = true; browser.noFlex = true;
@ -178,5 +224,7 @@
browser.touch = true; browser.touch = true;
} }
browser.keyboard = hasKeyboard(browser);
return browser; return browser;
}); });

View file

@ -1,4 +1,5 @@
define(['browser'], function (browser) { define(['browser'], function (browser) {
'use strict';
function canPlayH264() { function canPlayH264() {
var v = document.createElement('video'); var v = document.createElement('video');
@ -46,7 +47,7 @@ define(['browser'], function (browser) {
} }
function canPlayHlsWithMSE() { function canPlayHlsWithMSE() {
if (window.MediaSource != null && !browser.firefox) { if (window.MediaSource != null) {
// text tracks dont work with this in firefox // text tracks dont work with this in firefox
return true; return true;
} }
@ -58,7 +59,7 @@ define(['browser'], function (browser) {
var typeString; var typeString;
if (format == 'flac') { if (format === 'flac') {
if (browser.tizen) { if (browser.tizen) {
return true; return true;
} }
@ -67,7 +68,7 @@ define(['browser'], function (browser) {
} }
} }
else if (format == 'wma') { else if (format === 'wma') {
if (browser.tizen) { if (browser.tizen) {
return true; return true;
} }
@ -76,7 +77,7 @@ define(['browser'], function (browser) {
} }
} }
else if (format == 'opus') { else if (format === 'opus') {
typeString = 'audio/ogg; codecs="opus"'; typeString = 'audio/ogg; codecs="opus"';
if (document.createElement('audio').canPlayType(typeString).replace(/no/, '')) { if (document.createElement('audio').canPlayType(typeString).replace(/no/, '')) {
@ -86,7 +87,7 @@ define(['browser'], function (browser) {
return false; return false;
} }
if (format == 'webma') { if (format === 'webma') {
typeString = 'audio/webm'; typeString = 'audio/webm';
} else { } else {
typeString = 'audio/' + format; typeString = 'audio/' + format;
@ -117,7 +118,7 @@ define(['browser'], function (browser) {
} }
// Filter out browsers based on chromium that don't support mkv // Filter out browsers based on chromium that don't support mkv
if (userAgent.indexOf('vivaldi') != -1 || userAgent.indexOf('opera') != -1) { if (userAgent.indexOf('vivaldi') !== -1 || userAgent.indexOf('opera') !== -1) {
return false; return false;
} }
@ -138,13 +139,14 @@ define(['browser'], function (browser) {
function testCanPlayTs() { function testCanPlayTs() {
return browser.tizen || browser.web0s; return browser.tizen || browser.web0s || browser.edgeUwp;
} }
function getDirectPlayProfileForVideoContainer(container, videoAudioCodecs) { function getDirectPlayProfileForVideoContainer(container, videoAudioCodecs) {
var supported = false; var supported = false;
var profileContainer = container; var profileContainer = container;
var videoCodecs = [];
switch (container) { switch (container) {
@ -153,7 +155,7 @@ define(['browser'], function (browser) {
videoAudioCodecs = []; videoAudioCodecs = [];
break; break;
case 'avi': case 'avi':
supported = browser.edgeUwp; supported = browser.tizen || browser.edgeUwp;
break; break;
case 'mpg': case 'mpg':
case 'mpeg': case 'mpeg':
@ -169,16 +171,19 @@ define(['browser'], function (browser) {
break; break;
case 'mov': case 'mov':
supported = browser.chrome || browser.edgeUwp; supported = browser.chrome || browser.edgeUwp;
videoCodecs.push('h264');
break; break;
case 'm2ts': case 'm2ts':
supported = browser.tizen || browser.web0s || browser.edgeUwp; supported = browser.tizen || browser.web0s || browser.edgeUwp;
videoCodecs.push('h264');
break; break;
case 'wmv': case 'wmv':
supported = browser.tizen || browser.web0s || browser.edgeUwp; supported = browser.tizen || browser.web0s || browser.edgeUwp;
videoAudioCodecs = []; videoAudioCodecs = [];
break; break;
case 'ts': case 'ts':
supported = browser.tizen || browser.web0s || browser.edgeUwp; supported = testCanPlayTs();
videoCodecs.push('h264');
profileContainer = 'ts,mpegts'; profileContainer = 'ts,mpegts';
break; break;
default: default:
@ -192,6 +197,7 @@ define(['browser'], function (browser) {
return { return {
Container: profileContainer, Container: profileContainer,
Type: 'Video', Type: 'Video',
VideoCodec: videoCodecs.join(','),
AudioCodec: videoAudioCodecs.join(',') AudioCodec: videoAudioCodecs.join(',')
}; };
} }
@ -199,7 +205,7 @@ define(['browser'], function (browser) {
function getMaxBitrate() { function getMaxBitrate() {
if (browser.edgeUwp) { if (browser.edgeUwp) {
return 15000000; return 30000000;
} }
// 10mbps // 10mbps
@ -216,7 +222,7 @@ define(['browser'], function (browser) {
if (browser.tizen) { if (browser.tizen) {
// 2015 models // 2015 models
if (userAgent.indexOf('tizen 2.3') != -1) { if (userAgent.indexOf('tizen 2.3') !== -1) {
return 20000000; return 20000000;
} }
@ -239,7 +245,6 @@ define(['browser'], function (browser) {
var canPlayWebm = videoTestElement.canPlayType('video/webm').replace(/no/, ''); var canPlayWebm = videoTestElement.canPlayType('video/webm').replace(/no/, '');
var canPlayMkv = testCanPlayMkv(videoTestElement); var canPlayMkv = testCanPlayMkv(videoTestElement);
var canPlayTs = testCanPlayTs();
var profile = {}; var profile = {};
@ -269,19 +274,20 @@ define(['browser'], function (browser) {
} }
var mp3Added = false; var mp3Added = false;
if (canPlayMkv || canPlayTs) { if (canPlayMkv) {
if (supportsMp3VideoAudio) { if (supportsMp3VideoAudio) {
mp3Added = true; mp3Added = true;
videoAudioCodecs.push('mp3'); videoAudioCodecs.push('mp3');
hlsVideoAudioCodecs.push('mp3');
} }
} }
if (videoTestElement.canPlayType('video/mp4; codecs="avc1.640029, mp4a.40.2"').replace(/no/, '')) { if (videoTestElement.canPlayType('video/mp4; codecs="avc1.640029, mp4a.40.2"').replace(/no/, '')) {
videoAudioCodecs.push('aac'); videoAudioCodecs.push('aac');
hlsVideoAudioCodecs.push('aac'); hlsVideoAudioCodecs.push('aac');
} }
if (!mp3Added && supportsMp3VideoAudio) { if (supportsMp3VideoAudio) {
videoAudioCodecs.push('mp3'); if (!mp3Added) {
videoAudioCodecs.push('mp3');
}
hlsVideoAudioCodecs.push('mp3'); hlsVideoAudioCodecs.push('mp3');
} }
@ -342,12 +348,12 @@ define(['browser'], function (browser) {
['opus', 'mp3', 'aac', 'flac', 'webma', 'wma', 'wav'].filter(canPlayAudioFormat).forEach(function (audioFormat) { ['opus', 'mp3', 'aac', 'flac', 'webma', 'wma', 'wav'].filter(canPlayAudioFormat).forEach(function (audioFormat) {
profile.DirectPlayProfiles.push({ profile.DirectPlayProfiles.push({
Container: audioFormat == 'webma' ? 'webma,webm' : audioFormat, Container: audioFormat === 'webma' ? 'webma,webm' : audioFormat,
Type: 'Audio' Type: 'Audio'
}); });
// aac also appears in the m4a container // aac also appears in the m4a container
if (audioFormat == 'aac') { if (audioFormat === 'aac') {
profile.DirectPlayProfiles.push({ profile.DirectPlayProfiles.push({
Container: 'm4a', Container: 'm4a',
AudioCodec: audioFormat, AudioCodec: audioFormat,
@ -389,7 +395,7 @@ define(['browser'], function (browser) {
} }
// Can't use mkv on mobile because we have to use the native player controls and they won't be able to seek it // Can't use mkv on mobile because we have to use the native player controls and they won't be able to seek it
if (canPlayMkv && options.supportsCustomSeeking && !browser.tizen) { if (canPlayMkv && options.supportsCustomSeeking && !browser.tizen && options.enableMkvProgressive !== false) {
profile.TranscodingProfiles.push({ profile.TranscodingProfiles.push({
Container: 'mkv', Container: 'mkv',
Type: 'Video', Type: 'Video',
@ -400,28 +406,15 @@ define(['browser'], function (browser) {
}); });
} }
if (canPlayTs && options.supportsCustomSeeking && !browser.tizen && !browser.web0s) { if (canPlayHls() && options.enableHls !== false) {
profile.TranscodingProfiles.push({
Container: 'ts',
Type: 'Video',
AudioCodec: videoAudioCodecs.join(','),
VideoCodec: 'h264',
Context: 'Streaming',
CopyTimestamps: copyTimestamps,
// If audio transcoding is needed, limit channels to number of physical audio channels
// Trying to transcode to 5 channels when there are only 2 speakers generally does not sound good
MaxAudioChannels: physicalAudioChannels.toString()
});
}
if (canPlayHls()) {
profile.TranscodingProfiles.push({ profile.TranscodingProfiles.push({
Container: 'ts', Container: 'ts',
Type: 'Video', Type: 'Video',
AudioCodec: hlsVideoAudioCodecs.join(','), AudioCodec: hlsVideoAudioCodecs.join(','),
VideoCodec: 'h264', VideoCodec: 'h264',
Context: 'Streaming', Context: 'Streaming',
Protocol: 'hls' Protocol: 'hls',
MaxAudioChannels: physicalAudioChannels.toString()
}); });
} }
@ -565,6 +558,15 @@ define(['browser'], function (browser) {
}] }]
}); });
if (!browser.edgeUwp && !browser.tizen && !browser.web0s) {
profile.CodecProfiles[profile.CodecProfiles.length - 1].Conditions.push({
Condition: 'NotEquals',
Property: 'IsAVC',
Value: 'false',
IsRequired: false
});
}
profile.CodecProfiles.push({ profile.CodecProfiles.push({
Type: 'Video', Type: 'Video',
Codec: 'vpx', Codec: 'vpx',

View file

@ -1,3 +1,12 @@
button::-moz-focus-inner {
padding: 0;
border: 0;
}
button {
-webkit-border-fit: border !important;
}
.card { .card {
border: 0; border: 0;
font-size: inherit !important; font-size: inherit !important;
@ -82,10 +91,14 @@
transform: scale(1.16, 1.16); transform: scale(1.16, 1.16);
} }
.cardBox-mobile {
margin: 1px;
}
@media all and (min-width: 600px) { @media all and (min-width: 600px) {
.cardBox-mobile { .cardBox-mobile {
margin: 3px; margin: 2px;
} }
} }
@ -147,7 +160,7 @@
.cardImageContainer { .cardImageContainer {
/* Should be 0 with visualCardBox, but not really noticeable */ /* Should be 0 with visualCardBox, but not really noticeable */
border-radius: 2px; border-radius: 1px;
} }
} }
@ -179,6 +192,8 @@
bottom: 0; bottom: 0;
/* Needed in case this is a button */ /* Needed in case this is a button */
display: block; display: block;
/* Needed in safari */
height: 100%;
} }
.cardImage { .cardImage {
@ -192,6 +207,23 @@
background-position: center bottom; background-position: center bottom;
} }
.cardImage-img {
max-height: 100%;
max-width: 100%;
/* This is simply for lazy image purposes, to ensure the image is visible sooner when scrolling */
min-height: 70%;
min-width: 70%;
align-self: flex-end;
position: static;
}
.coveredImage-img {
max-height: none;
max-width: none;
height: 100%;
width: 100%;
}
.coveredImage { .coveredImage {
background-size: 100% 100%; background-size: 100% 100%;
background-position: center center; background-position: center center;
@ -211,12 +243,8 @@
} }
.visualCardBox-cardFooter { .visualCardBox-cardFooter {
border-bottom-left-radius: 2px; border-bottom-left-radius: 1px;
border-bottom-right-radius: 2px; border-bottom-right-radius: 1px;
-moz-box-shadow: 0 2px 4px rgba(0,0,0,0.1);
-ms-box-shadow: 0 2px 4px rgba(0,0,0,0.1);
-webkit-box-shadow: 0 2px 4px rgba(0,0,0,0.1);
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
} }
.innerCardFooter { .innerCardFooter {
@ -245,6 +273,11 @@
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
color: inherit; color: inherit;
text-align: left;
}
.singleCardText {
padding: .5em;
} }
.cardTextCentered { .cardTextCentered {
@ -259,8 +292,9 @@
margin-right: 2em; margin-right: 2em;
} }
.cardCenteredText { .cardDefaultText {
white-space: normal; white-space: normal;
text-align: center;
} }
.textActionButton { .textActionButton {
@ -315,15 +349,21 @@
.cardOverlayButton { .cardOverlayButton {
color: #fff !important; color: #fff !important;
background-color: rgba(0,0,0,.7) !important; background-color: rgba(0,0,0,.8) !important;
border-radius: 500px; border-radius: 500px;
position: absolute; position: absolute;
bottom: 0; bottom: 0;
right: 0; right: 0;
margin: 0 .35em .5em 0; margin: 0 .35em .5em 0;
z-index: 1; z-index: 1;
/*opacity: 0;
transition: opacity 0.5s ease-in; /* vendorless fallback */ */;
} }
/*.card:hover .cardOverlayButton {
opacity: 1;
}*/
.cardOverlayButton:hover { .cardOverlayButton:hover {
background-color: rgba(0,0,0,.9) !important; background-color: rgba(0,0,0,.9) !important;
transition: background-color .5s ease-out; transition: background-color .5s ease-out;
@ -375,7 +415,7 @@
} }
.overflowBackdropCard-scalable { .overflowBackdropCard-scalable {
width: 84%; width: 80%;
max-width: 400px; max-width: 400px;
} }
@ -514,7 +554,6 @@
} }
} }
@media all and (min-width: 1600px) { @media all and (min-width: 1600px) {
.portraitCard-scalable { .portraitCard-scalable {
@ -524,12 +563,27 @@
.smallBackdropCard-scalable { .smallBackdropCard-scalable {
width: 12.5%; width: 12.5%;
} }
.backdropCard-scalable {
width: 20%;
}
.squareCard-scalable {
width: 12.5%;
}
} }
@media all and (min-width: 1800px) { @media all and (min-width: 1800px) {
.smallBackdropCard-scalable {
width: 10%;
}
}
@media all and (min-width: 1920px) {
.squareCard-scalable { .squareCard-scalable {
width: 12.5%; width: 11.111111111111111111111111111111%;
} }
.smallBackdropCard-scalable { .smallBackdropCard-scalable {
@ -539,10 +593,6 @@
@media all and (min-width: 2100px) { @media all and (min-width: 2100px) {
.squareCard-scalable {
width: 11.111111111111111111111111111111%;
}
.backdropCard-scalable { .backdropCard-scalable {
width: 20%; width: 20%;
} }
@ -582,6 +632,10 @@
width: 16.66666666666666667%; width: 16.66666666666666667%;
} }
.layout-tv .personCard-scalable {
width: 14.285714285714285714285714285714%; @media all and (min-width: 1600px) {
.layout-tv .backdropCard-scalable {
width: 25%;
}
} }

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,5 @@
define(['datetime', 'imageLoader', 'connectionManager', 'layoutManager'], function (datetime, imageLoader, connectionManager, layoutManager) { define(['datetime', 'imageLoader', 'connectionManager', 'layoutManager'], function (datetime, imageLoader, connectionManager, layoutManager) {
'use strict';
function buildChapterCardsHtml(item, chapters, options) { function buildChapterCardsHtml(item, chapters, options) {
@ -6,7 +7,7 @@ define(['datetime', 'imageLoader', 'connectionManager', 'layoutManager'], functi
var mediaStreams = ((item.MediaSources || [])[0] || {}).MediaStreams || []; var mediaStreams = ((item.MediaSources || [])[0] || {}).MediaStreams || [];
var videoStream = mediaStreams.filter(function (i) { var videoStream = mediaStreams.filter(function (i) {
return i.Type == 'Video'; return i.Type === 'Video';
})[0] || {}; })[0] || {};
var shape = (options.backdropShape || 'backdrop'); var shape = (options.backdropShape || 'backdrop');
@ -32,7 +33,7 @@ define(['datetime', 'imageLoader', 'connectionManager', 'layoutManager'], functi
for (var i = 0, length = chapters.length; i < length; i++) { for (var i = 0, length = chapters.length; i < length; i++) {
if (options.rows && itemsInRow == 0) { if (options.rows && itemsInRow === 0) {
html += '<div class="cardColumn">'; html += '<div class="cardColumn">';
} }
@ -91,22 +92,7 @@ define(['datetime', 'imageLoader', 'connectionManager', 'layoutManager'], functi
cardBoxCssClass += ' cardBox-focustransform'; cardBoxCssClass += ' cardBox-focustransform';
} }
var html = '\ var html = '<button type="button" class="' + className + '"' + dataAttributes + '><div class="' + cardBoxCssClass + '"><div class="cardScalable"><div class="cardPadder-' + shape + '"></div><div class="cardContent">' + cardImageContainer + '</div><div class="innerCardFooter">' + nameHtml + '</div></div></div></div></button>';
<button type="button" class="' + className + '"' + dataAttributes + '> \
<div class="' + cardBoxCssClass + '">\
<div class="cardScalable">\
<div class="cardPadder-'+ shape + '"></div>\
<div class="cardContent">\
' + cardImageContainer + '\
</div>\
<div class="innerCardFooter">\
' + nameHtml + '\
</div>\
</div>\
</div>\
</div>\
</button>'
;
return html; return html;
} }

View file

@ -1,133 +1,17 @@
define(['imageLoader', 'itemShortcuts', 'connectionManager', 'layoutManager'], function (imageLoader, itemShortcuts, connectionManager, layoutManager) { define(['cardBuilder'], function (cardBuilder) {
'use strict';
function buildPeopleCardsHtml(people, options) {
var className = 'card ' + (options.shape || 'portrait') + 'Card personCard';
if (options.block || options.rows) {
className += ' block';
}
var html = '';
var itemsInRow = 0;
var serverId = options.serverId;
var apiClient = connectionManager.getApiClient(serverId);
for (var i = 0, length = people.length; i < length; i++) {
if (options.rows && itemsInRow == 0) {
html += '<div class="cardColumn">';
}
var person = people[i];
html += buildPersonCard(person, apiClient, serverId, options, className);
itemsInRow++;
if (options.rows && itemsInRow >= options.rows) {
itemsInRow = 0;
html += '</div>';
}
}
return html;
}
function getImgUrl(person, maxWidth, apiClient) {
if (person.PrimaryImageTag) {
return apiClient.getScaledImageUrl(person.Id, {
maxWidth: maxWidth,
tag: person.PrimaryImageTag,
type: "Primary"
});
}
return null;
}
function buildPersonCard(person, apiClient, serverId, options, className) {
className += " itemAction scalableCard personCard-scalable";
className += " " + (options.shape || 'portrait') + 'Card-scalable';
var imgUrl = getImgUrl(person, options.width, apiClient);
var cardImageContainerClass = 'cardImageContainer';
if (options.coverImage) {
cardImageContainerClass += ' coveredImage';
}
var cardImageContainer = imgUrl ? ('<div class="' + cardImageContainerClass + ' lazy" data-src="' + imgUrl + '">') : ('<div class="' + cardImageContainerClass + '">');
if (!imgUrl) {
cardImageContainer += '<i class="md-icon cardImageIcon">person</i>';
}
var nameHtml = '';
nameHtml += '<div class="cardText">' + person.Name + '</div>';
if (person.Role) {
nameHtml += '<div class="cardText cardText-secondary">as ' + person.Role + '</div>';
}
else if (person.Type) {
nameHtml += '<div class="cardText cardText-secondary">' + Globalize.translate('core#' + person.Type) + '</div>';
} else {
nameHtml += '<div class="cardText cardText-secondary">&nbsp;</div>';
}
var cardBoxCssClass = 'visualCardBox cardBox';
if (layoutManager.tv) {
cardBoxCssClass += ' cardBox-focustransform';
}
var html = '\
<button type="button" data-isfolder="' + person.IsFolder + '" data-type="' + person.Type + '" data-action="link" data-id="' + person.Id + '" data-serverid="' + serverId + '" raised class="' + className + '"> \
<div class="' + cardBoxCssClass + '">\
<div class="cardScalable visualCardBox-cardScalable">\
<div class="cardPadder-portrait"></div>\
<div class="cardContent">\
' + cardImageContainer + '\
</div>\
</div>\
</div>\
<div class="cardFooter visualCardBox-cardFooter">\
' + nameHtml + '\
</div>\
</div>\
</button>'
;
return html;
}
function buildPeopleCards(items, options) { function buildPeopleCards(items, options) {
if (options.parentContainer) { options = Object.assign(options || {}, {
// Abort if the container has been disposed cardLayout: true,
if (!document.body.contains(options.parentContainer)) { centerText: true,
return; showTitle: true,
} cardFooterAside: 'none',
showPersonRoleOrType: true,
if (items.length) { cardCssClass: 'personCard'
options.parentContainer.classList.remove('hide'); });
} else { cardBuilder.buildCards(items, options);
options.parentContainer.classList.add('hide');
return;
}
}
var html = buildPeopleCardsHtml(items, options);
options.itemsContainer.innerHTML = html;
imageLoader.lazyChildren(options.itemsContainer);
itemShortcuts.off(options.itemsContainer);
itemShortcuts.on(options.itemsContainer);
} }
return { return {

View file

@ -1,4 +1,5 @@
define(['dialog', 'globalize'], function (dialog, globalize) { define(['dialog', 'globalize'], function (dialog, globalize) {
'use strict';
return function (text, title) { return function (text, title) {
@ -15,21 +16,21 @@ define(['dialog', 'globalize'], function (dialog, globalize) {
var items = []; var items = [];
items.push({ items.push({
name: globalize.translate('sharedcomponents#ButtonOk'), name: options.cancelText || globalize.translate('sharedcomponents#ButtonCancel'),
id: 'ok', id: 'cancel',
type: 'submit' type: options.primary === 'cancel' ? 'submit' : 'cancel'
}); });
items.push({ items.push({
name: globalize.translate('sharedcomponents#ButtonCancel'), name: options.confirmText || globalize.translate('sharedcomponents#ButtonOk'),
id: 'cancel', id: 'ok',
type: 'cancel' type: options.primary === 'cancel' ? 'cancel' : 'submit'
}); });
options.buttons = items; options.buttons = items;
return dialog(options).then(function (result) { return dialog(options).then(function (result) {
if (result == 'ok') { if (result === 'ok') {
return Promise.resolve(); return Promise.resolve();
} }

View file

@ -1,4 +1,5 @@
define([], function () { define([], function () {
'use strict';
function replaceAll(str, find, replace) { function replaceAll(str, find, replace) {

View file

@ -1,4 +1,5 @@
define(['globalize'], function (globalize) { define(['globalize'], function (globalize) {
'use strict';
function parseISO8601Date(s, toLocal) { function parseISO8601Date(s, toLocal) {
@ -40,12 +41,12 @@
} }
// if there's a timezone, calculate it // if there's a timezone, calculate it
if (d[8] != "Z" && d[10]) { if (d[8] !== "Z" && d[10]) {
var offset = d[10] * 60 * 60 * 1000; var offset = d[10] * 60 * 60 * 1000;
if (d[11]) { if (d[11]) {
offset += d[11] * 60 * 1000; offset += d[11] * 60 * 1000;
} }
if (d[9] == "-") { if (d[9] === "-") {
ms -= offset; ms -= offset;
} else { } else {
ms += offset; ms += offset;
@ -103,60 +104,36 @@
return false; return false;
}(); }();
function toLocaleString(date) { function getCurrentLocale() {
var currentLocale = globalize.getCurrentLocale(); var locale = globalize.getCurrentLocale();
return locale;
}
function toLocaleString(date, options) {
var currentLocale = getCurrentLocale();
return currentLocale && toLocaleTimeStringSupportsLocales ? return currentLocale && toLocaleTimeStringSupportsLocales ?
date.toLocaleString(currentLocale) : date.toLocaleString(currentLocale, options || {}) :
date.toLocaleString(); date.toLocaleString();
} }
function getLocaleDateStringParts(date) { function toLocaleDateString(date, options) {
var day = getDayName(date); var currentLocale = getCurrentLocale();
date = toLocaleDateString(date);
var parts = [];
if (date.toLowerCase().indexOf(day.toLowerCase()) == -1) {
parts.push(day);
}
parts.push(date);
return parts;
}
function getDayName(date) {
var weekday = [];
weekday[0] = globalize.translate('sharedcomponents#Sunday');
weekday[1] = globalize.translate('sharedcomponents#Monday');
weekday[2] = globalize.translate('sharedcomponents#Tuesday');
weekday[3] = globalize.translate('sharedcomponents#Wednesday');
weekday[4] = globalize.translate('sharedcomponents#Thursday');
weekday[5] = globalize.translate('sharedcomponents#Friday');
weekday[6] = globalize.translate('sharedcomponents#Saturday');
return weekday[date.getDay()];
}
function toLocaleDateString(date) {
var currentLocale = globalize.getCurrentLocale();
return currentLocale && toLocaleTimeStringSupportsLocales ? return currentLocale && toLocaleTimeStringSupportsLocales ?
date.toLocaleDateString(currentLocale) : date.toLocaleDateString(currentLocale, options || {}) :
date.toLocaleDateString(); date.toLocaleDateString();
} }
function toLocaleTimeString(date) { function toLocaleTimeString(date, options) {
var currentLocale = globalize.getCurrentLocale(); var currentLocale = getCurrentLocale();
return currentLocale && toLocaleTimeStringSupportsLocales ? return currentLocale && toLocaleTimeStringSupportsLocales ?
date.toLocaleTimeString(currentLocale) : date.toLocaleTimeString(currentLocale, options || {}).toLowerCase() :
date.toLocaleTimeString(); date.toLocaleTimeString().toLowerCase();
} }
function getDisplayTime(date) { function getDisplayTime(date) {
@ -171,36 +148,12 @@
} }
} }
var time = toLocaleTimeString(date); return toLocaleTimeString(date, {
var timeLower = time.toLowerCase(); hour: 'numeric',
minute: '2-digit'
if (timeLower.indexOf('am') != -1 || timeLower.indexOf('pm') != -1) { });
time = timeLower;
var hour = date.getHours() % 12;
var suffix = date.getHours() > 11 ? 'pm' : 'am';
if (!hour) {
hour = 12;
}
var minutes = date.getMinutes();
if (minutes < 10) {
minutes = '0' + minutes;
}
time = hour + ':' + minutes + suffix;
} else {
var timeParts = time.split(':');
// Trim off seconds
if (timeParts.length > 2) {
timeParts.length -= 1;
time = timeParts.join(':');
}
}
return time;
} }
function isRelativeDay(date, offsetInDays) { function isRelativeDay(date, offsetInDays) {
@ -209,7 +162,7 @@
yesterday.setDate(day); // automatically adjusts month/year appropriately yesterday.setDate(day); // automatically adjusts month/year appropriately
return date.getFullYear() == yesterday.getFullYear() && date.getMonth() == yesterday.getMonth() && date.getDate() == day; return date.getFullYear() === yesterday.getFullYear() && date.getMonth() === yesterday.getMonth() && date.getDate() === day;
} }
return { return {
@ -218,7 +171,6 @@
toLocaleDateString: toLocaleDateString, toLocaleDateString: toLocaleDateString,
toLocaleString: toLocaleString, toLocaleString: toLocaleString,
getDisplayTime: getDisplayTime, getDisplayTime: getDisplayTime,
isRelativeDay: isRelativeDay, isRelativeDay: isRelativeDay
getLocaleDateStringParts: getLocaleDateStringParts
}; };
}); });

View file

@ -1,20 +1,5 @@
define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 'require', 'material-icons', 'emby-button', 'paper-icon-button-light', 'emby-input', 'formDialogStyle'], function (dialogHelper, dom, layoutManager, scrollHelper, globalize, require) { define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 'require', 'material-icons', 'emby-button', 'paper-icon-button-light', 'emby-input', 'formDialogStyle'], function (dialogHelper, dom, layoutManager, scrollHelper, globalize, require) {
'use strict';
function showTvDialog(options) {
return new Promise(function (resolve, reject) {
require(['actionsheet'], function (actionSheet) {
actionSheet.show({
title: options.text,
items: options.buttons,
timeout: options.timeout
}).then(resolve, reject);
});
});
}
function showDialog(options, template) { function showDialog(options, template) {
@ -23,10 +8,10 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
scrollY: false scrollY: false
}; };
if (layoutManager.tv) { var enableTvLayout = layoutManager.tv;
if (enableTvLayout) {
dialogOptions.size = 'fullscreen'; dialogOptions.size = 'fullscreen';
} else {
//dialogOptions.size = 'mini';
} }
var dlg = dialogHelper.createDialog(dialogOptions); var dlg = dialogHelper.createDialog(dialogOptions);
@ -35,17 +20,29 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
dlg.innerHTML = globalize.translateHtml(template, 'sharedcomponents'); dlg.innerHTML = globalize.translateHtml(template, 'sharedcomponents');
if (layoutManager.tv) { dlg.style['align-items'] = 'center';
scrollHelper.centerFocus.on(dlg.querySelector('.formDialogContent'), false); dlg.style['justify-content'] = 'center';
var formDialogContent = dlg.querySelector('.formDialogContent');
formDialogContent.style['flex-grow'] = 'initial';
if (enableTvLayout) {
formDialogContent.style['max-width'] = '50%';
formDialogContent.style['max-height'] = '60%';
scrollHelper.centerFocus.on(formDialogContent, false);
} else { } else {
dlg.querySelector('.dialogContentInner').classList.add('dialogContentInner-mini'); formDialogContent.style.maxWidth = (Math.min((options.buttons.length * 150) + 200, dom.getWindowSize().innerWidth - 50)) + 'px';
dlg.classList.add('dialog-fullscreen-lowres');
} }
//dlg.querySelector('.btnCancel').addEventListener('click', function (e) { //dlg.querySelector('.btnCancel').addEventListener('click', function (e) {
// dialogHelper.close(dlg); // dialogHelper.close(dlg);
//}); //});
dlg.querySelector('.formDialogHeaderTitle').innerHTML = options.title || ''; if (options.title) {
dlg.querySelector('.formDialogHeaderTitle').innerHTML = options.title || '';
} else {
dlg.querySelector('.formDialogHeaderTitle').classList.add('hide');
}
dlg.querySelector('.text').innerHTML = options.html || options.text || ''; dlg.querySelector('.text').innerHTML = options.html || options.text || '';
@ -54,9 +51,9 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
for (i = 0, length = options.buttons.length; i < length; i++) { for (i = 0, length = options.buttons.length; i < length; i++) {
var item = options.buttons[i]; var item = options.buttons[i];
var autoFocus = i == 0 ? ' autofocus' : ''; var autoFocus = i === 0 ? ' autofocus' : '';
var buttonClass = 'btnOption raised block formDialogFooterItem'; var buttonClass = 'btnOption raised formDialogFooterItem formDialogFooterItem-autosize';
if (item.type) { if (item.type) {
buttonClass += ' button-' + item.type; buttonClass += ' button-' + item.type;
@ -65,8 +62,6 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
html += '<button is="emby-button" type="button" class="' + buttonClass + '" data-id="' + item.id + '"' + autoFocus + '>' + item.name + '</button>'; html += '<button is="emby-button" type="button" class="' + buttonClass + '" data-id="' + item.id + '"' + autoFocus + '>' + item.name + '</button>';
} }
dlg.style.minWidth = (Math.min(options.buttons.length * 150, dom.getWindowSize().innerWidth - 50)) + 'px';
dlg.querySelector('.formDialogFooter').innerHTML = html; dlg.querySelector('.formDialogFooter').innerHTML = html;
var dialogResult; var dialogResult;
@ -82,7 +77,7 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
return dialogHelper.open(dlg).then(function () { return dialogHelper.open(dlg).then(function () {
if (layoutManager.tv) { if (enableTvLayout) {
scrollHelper.centerFocus.off(dlg.querySelector('.formDialogContent'), false); scrollHelper.centerFocus.off(dlg.querySelector('.formDialogContent'), false);
} }
@ -106,10 +101,6 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
options = text; options = text;
} }
if (layoutManager.tv) {
return showTvDialog(options);
}
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
require(['text!./dialog.template.html'], function (template) { require(['text!./dialog.template.html'], function (template) {
showDialog(options, template).then(resolve, reject); showDialog(options, template).then(resolve, reject);

View file

@ -1,16 +1,15 @@
<div class="formDialogHeader"> <div class="formDialogHeader formDialogHeader-clear" style="justify-content:center;">
<h3 class="formDialogHeaderTitle" style="margin-left:.75em;"></h3> <h1 class="formDialogHeaderTitle" style="margin-left:0;margin-top: .5em;padding: 0 1em;"></h1>
<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1" style="visibility:hidden;"><i class="md-icon">&#xE5C4;</i></button>
</div> </div>
<div class="formDialogContent smoothScrollY"> <div class="formDialogContent smoothScrollY">
<div class="dialogContentInner dialog-content-centered" style="padding-top:2em;"> <div class="dialogContentInner dialog-content-centered" style="padding-top:2em;padding-bottom: 2em; text-align: center;">
<div class="text"> <div class="text">
</div> </div>
<div class="formDialogFooter">
</div>
</div> </div>
</div>
<div class="formDialogFooter formDialogFooter-clear formDialogFooter-flex" style="padding-bottom: 1.5em;">
</div> </div>

View file

@ -13,14 +13,14 @@
.dialog { .dialog {
margin: 0; margin: 0;
border-radius: 1px; border-radius: 4px;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
box-shadow: 0 16px 24px 2px rgba(0, 0, 0, 0.14), 0 6px 30px 5px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.4);
border: 0; border: 0;
padding: 0; padding: 0;
will-change: transform; will-change: transform;
/* Strict does not work well with actionsheet */ /* Strict does not work well with actionsheet */
contain: style; contain: style;
box-shadow: 0 16px 24px 2px rgba(0, 0, 0, 0.14), 0 6px 30px 5px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.4);
} }
.dialog-fixedSize { .dialog-fixedSize {
@ -37,16 +37,19 @@
left: 0; left: 0;
right: 0; right: 0;
margin: 0; margin: 0;
box-shadow: none;
} }
@media all and (max-width: 1280px), all and (max-height: 720px) { @media all and (max-width: 1280px), all and (max-height: 720px) {
.dialog-fixedSize {
.dialog-fixedSize, .dialog-fullscreen-lowres {
position: fixed !important; position: fixed !important;
top: 0 !important; top: 0 !important;
bottom: 0 !important; bottom: 0 !important;
left: 0 !important; left: 0 !important;
right: 0 !important; right: 0 !important;
margin: 0 !important; margin: 0 !important;
box-shadow: none;
} }
} }
@ -92,5 +95,5 @@
} }
.dialogBackdropOpened { .dialogBackdropOpened {
opacity: .7; opacity: .6;
} }

View file

@ -1,4 +1,5 @@
define(['historyManager', 'focusManager', 'browser', 'layoutManager', 'inputManager', 'dom', 'css!./dialoghelper.css', 'scrollStyles'], function (historyManager, focusManager, browser, layoutManager, inputManager, dom) { define(['historyManager', 'focusManager', 'browser', 'layoutManager', 'inputManager', 'dom', 'css!./dialoghelper.css', 'scrollStyles'], function (historyManager, focusManager, browser, layoutManager, inputManager, dom) {
'use strict';
var globalOnOpenCallback; var globalOnOpenCallback;
@ -27,7 +28,7 @@
} }
} }
function dialogHashHandler(dlg, hash, resolve) { function DialogHashHandler(dlg, hash, resolve) {
var self = this; var self = this;
self.originalUrl = window.location.href; self.originalUrl = window.location.href;
@ -36,7 +37,7 @@
function onHashChange(e) { function onHashChange(e) {
var isBack = self.originalUrl == window.location.href; var isBack = self.originalUrl === window.location.href;
if (isBack || !isOpened(dlg)) { if (isBack || !isOpened(dlg)) {
window.removeEventListener('popstate', onHashChange); window.removeEventListener('popstate', onHashChange);
@ -50,10 +51,11 @@
function onBackCommand(e) { function onBackCommand(e) {
if (e.detail.command == 'back') { if (e.detail.command === 'back') {
self.closedByBack = true; self.closedByBack = true;
closeDialog(dlg);
e.preventDefault(); e.preventDefault();
e.stopPropagation();
closeDialog(dlg);
} }
} }
@ -74,7 +76,7 @@
if (!self.closedByBack && isHistoryEnabled(dlg)) { if (!self.closedByBack && isHistoryEnabled(dlg)) {
var state = history.state || {}; var state = history.state || {};
if (state.dialogId == hash) { if (state.dialogId === hash) {
history.back(); history.back();
} }
} }
@ -83,7 +85,7 @@
activeElement.focus(); activeElement.focus();
} }
if (dlg.getAttribute('data-removeonclose') != 'false') { if (dlg.getAttribute('data-removeonclose') !== 'false') {
removeCenterFocus(dlg); removeCenterFocus(dlg);
var dialogContainer = dlg.dialogContainer; var dialogContainer = dlg.dialogContainer;
@ -117,8 +119,12 @@
addBackdropOverlay(dlg); addBackdropOverlay(dlg);
dlg.classList.add('opened'); dlg.classList.add('opened');
dlg.dispatchEvent(new CustomEvent('open', {
bubbles: false,
cancelable: false
}));
if (dlg.getAttribute('data-lockscroll') == 'true' && !document.body.classList.contains('noScroll')) { if (dlg.getAttribute('data-lockscroll') === 'true' && !document.body.classList.contains('noScroll')) {
document.body.classList.add('noScroll'); document.body.classList.add('noScroll');
removeScrollLockOnClose = true; removeScrollLockOnClose = true;
} }
@ -126,7 +132,7 @@
animateDialogOpen(dlg); animateDialogOpen(dlg);
if (isHistoryEnabled(dlg)) { if (isHistoryEnabled(dlg)) {
historyManager.pushState({ dialogId: hash }, "Dialog", hash); historyManager.pushState({ dialogId: hash }, "Dialog", '#' + hash);
window.addEventListener('popstate', onHashChange); window.addEventListener('popstate', onHashChange);
} else { } else {
@ -149,7 +155,7 @@
}, 0); }, 0);
dom.addEventListener((dlg.dialogContainer || backdrop), 'click', function (e) { dom.addEventListener((dlg.dialogContainer || backdrop), 'click', function (e) {
if (e.target == dlg.dialogContainer) { if (e.target === dlg.dialogContainer) {
close(dlg); close(dlg);
} }
}, { }, {
@ -158,7 +164,7 @@
} }
function isHistoryEnabled(dlg) { function isHistoryEnabled(dlg) {
return dlg.getAttribute('data-history') == 'true'; return dlg.getAttribute('data-history') === 'true';
} }
function open(dlg) { function open(dlg) {
@ -180,7 +186,7 @@
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
new dialogHashHandler(dlg, 'dlg' + new Date().getTime(), resolve); new DialogHashHandler(dlg, 'dlg' + new Date().getTime(), resolve);
}); });
} }
@ -207,7 +213,7 @@
{ transform: 'scale(0)', offset: 0 }, { transform: 'scale(0)', offset: 0 },
{ transform: 'none', offset: 1 }]; { transform: 'none', offset: 1 }];
var timing = elem.animationConfig.entry.timing; var timing = elem.animationConfig.entry.timing;
return elem.animate(keyframes, timing).onfinish = onFinish; elem.animate(keyframes, timing).onfinish = onFinish;
} }
function slideUp(elem, onFinish) { function slideUp(elem, onFinish) {
@ -216,7 +222,7 @@
{ transform: 'translate3d(0,30%,0)', opacity: 0, offset: 0 }, { transform: 'translate3d(0,30%,0)', opacity: 0, offset: 0 },
{ transform: 'none', opacity: 1, offset: 1 }]; { transform: 'none', opacity: 1, offset: 1 }];
var timing = elem.animationConfig.entry.timing; var timing = elem.animationConfig.entry.timing;
return elem.animate(keyframes, timing).onfinish = onFinish; elem.animate(keyframes, timing).onfinish = onFinish;
} }
function fadeIn(elem, onFinish) { function fadeIn(elem, onFinish) {
@ -225,7 +231,7 @@
{ opacity: '0', offset: 0 }, { opacity: '0', offset: 0 },
{ opacity: '1', offset: 1 }]; { opacity: '1', offset: 1 }];
var timing = elem.animationConfig.entry.timing; var timing = elem.animationConfig.entry.timing;
return elem.animate(keyframes, timing).onfinish = onFinish; elem.animate(keyframes, timing).onfinish = onFinish;
} }
function scaleDown(elem) { function scaleDown(elem) {
@ -277,18 +283,18 @@
})); }));
} }
}; };
if (!dlg.animationConfig || !dlg.animate) { if (!dlg.animationConfig) {
onAnimationFinish(); onAnimationFinish();
return; return;
} }
var animation; var animation;
if (dlg.animationConfig.exit.name == 'fadeout') { if (dlg.animationConfig.exit.name === 'fadeout') {
animation = fadeOut(dlg); animation = fadeOut(dlg);
} else if (dlg.animationConfig.exit.name == 'scaledown') { } else if (dlg.animationConfig.exit.name === 'scaledown') {
animation = scaleDown(dlg); animation = scaleDown(dlg);
} else if (dlg.animationConfig.exit.name == 'slidedown') { } else if (dlg.animationConfig.exit.name === 'slidedown') {
animation = slideDown(dlg); animation = slideDown(dlg);
} else { } else {
onAnimationFinish(); onAnimationFinish();
@ -303,20 +309,20 @@
var onAnimationFinish = function () { var onAnimationFinish = function () {
focusManager.pushScope(dlg); focusManager.pushScope(dlg);
if (dlg.getAttribute('data-autofocus') == 'true') { if (dlg.getAttribute('data-autofocus') === 'true') {
focusManager.autoFocus(dlg); focusManager.autoFocus(dlg);
} }
}; };
if (!dlg.animationConfig || !dlg.animate) { if (!dlg.animationConfig) {
onAnimationFinish(); onAnimationFinish();
return; return;
} }
if (dlg.animationConfig.entry.name == 'fadein') { if (dlg.animationConfig.entry.name === 'fadein') {
fadeIn(dlg, onAnimationFinish); fadeIn(dlg, onAnimationFinish);
} else if (dlg.animationConfig.entry.name == 'scaleup') { } else if (dlg.animationConfig.entry.name === 'scaleup') {
scaleUp(dlg, onAnimationFinish); scaleUp(dlg, onAnimationFinish);
} else if (dlg.animationConfig.entry.name == 'slideup') { } else if (dlg.animationConfig.entry.name === 'slideup') {
slideUp(dlg, onAnimationFinish); slideUp(dlg, onAnimationFinish);
} }
} }
@ -327,7 +333,7 @@
return options.lockScroll; return options.lockScroll;
} }
if (options.size == 'fullscreen') { if (options.size === 'fullscreen') {
return true; return true;
} }

View file

@ -1,8 +1,9 @@
define([], function () { define([], function () {
'use strict';
function parentWithAttribute(elem, name, value) { function parentWithAttribute(elem, name, value) {
while ((value ? elem.getAttribute(name) != value : !elem.getAttribute(name))) { while ((value ? elem.getAttribute(name) !== value : !elem.getAttribute(name))) {
elem = elem.parentNode; elem = elem.parentNode;
if (!elem || !elem.getAttribute) { if (!elem || !elem.getAttribute) {
@ -20,7 +21,7 @@ define([], function () {
tagNames = [tagNames]; tagNames = [tagNames];
} }
while (tagNames.indexOf(elem.tagName || '') == -1) { while (tagNames.indexOf(elem.tagName || '') === -1) {
elem = elem.parentNode; elem = elem.parentNode;
if (!elem) { if (!elem) {

View file

@ -4,7 +4,6 @@
align-items: center; align-items: center;
box-sizing: border-box; box-sizing: border-box;
margin: 0 .29em; margin: 0 .29em;
background: transparent;
text-align: center; text-align: center;
font-size: inherit; font-size: inherit;
font-family: inherit; font-family: inherit;
@ -27,52 +26,57 @@
position: relative; position: relative;
overflow: hidden; overflow: hidden;
font-weight: 500; font-weight: 500;
text-transform: uppercase;
/* Disable webkit tap highlighting */ /* Disable webkit tap highlighting */
-webkit-tap-highlight-color: rgba(0,0,0,0); -webkit-tap-highlight-color: rgba(0,0,0,0);
} }
.emby-button.raised, .emby-button.fab { .emby-button::-moz-focus-inner {
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12), 0 3px 1px -2px rgba(0, 0, 0, 0.2); border: 0;
} }
.emby-button > i { .button-flat {
/* For non-fab buttons that have icons */ background: transparent;
font-size: 1.5em; box-shadow: none;
width: auto; text-transform: uppercase;
}
.emby-button > i {
/* For non-fab buttons that have icons */
font-size: 1.36em;
width: auto;
height: auto;
}
.fab {
display: inline-flex;
border-radius: 50%;
background-color: #444;
padding: .6em;
box-sizing: border-box;
align-items: center;
justify-content: center;
text-align: center;
color: #fff;
margin: 0;
}
.fab > i {
height: auto; height: auto;
width: auto;
vertical-align: middle;
font-size: 2.85em;
} }
.emby-button.fab {
display: inline-flex;
border-radius: 50%;
background-color: #444;
padding: .6em;
box-sizing: border-box;
align-items: center;
justify-content: center;
text-align: center;
color: #fff;
margin: 0;
}
.emby-button.fab > i {
height: auto;
width: auto;
vertical-align: middle;
font-size: 2.85em;
}
.emby-button-noflex { .emby-button-noflex {
display: inline-block; display: inline-block;
white-space: nowrap; white-space: nowrap;
} }
.emby-button.fab.mini { .fab.mini {
padding: 8px; padding: 8px;
} }
.emby-button.fab.mini > i { .fab.mini > i {
height: auto; height: auto;
width: auto; width: auto;
font-size: 1.72em; font-size: 1.72em;
@ -86,7 +90,7 @@
width: 100%; width: 100%;
} }
.emby-button.raised:focus { .raised:focus {
box-shadow: 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12), 0 5px 5px -3px rgba(0, 0, 0, 0.4); box-shadow: 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12), 0 5px 5px -3px rgba(0, 0, 0, 0.4);
transition: box-shadow 0.28s cubic-bezier(0.4, 0, 0.2, 1); transition: box-shadow 0.28s cubic-bezier(0.4, 0, 0.2, 1);
} }
@ -95,22 +99,10 @@
margin-left: .5em; margin-left: .5em;
} }
.emby-button span + i { .emby-button > span + i {
margin-left: .5em; margin-left: .5em;
} }
.emby-button.iconRight > i {
margin-left: auto;
margin-right: .25em;
}
.emby-button-noflex.iconRight > i {
position: absolute;
right: 0;
top: 25%;
margin-right: .5em;
}
.paper-icon-button-light { .paper-icon-button-light {
position: relative; position: relative;
display: inline-flex; display: inline-flex;
@ -149,6 +141,10 @@
justify-content: center; justify-content: center;
} }
.paper-icon-button-light::-moz-focus-inner {
border: 0;
}
.paper-icon-button-light[disabled] { .paper-icon-button-light[disabled] {
opacity: .3; opacity: .3;
} }
@ -156,7 +152,7 @@
.paper-icon-button-light > i { .paper-icon-button-light > i {
width: auto; width: auto;
height: auto; height: auto;
font-size: 1.72em; font-size: 1.6em;
/* Make sure its on top of the ripple */ /* Make sure its on top of the ripple */
position: relative; position: relative;
z-index: 1; z-index: 1;

View file

@ -1,4 +1,5 @@
define(['browser', 'dom', 'css!./emby-button', 'registerElement'], function (browser, dom) { define(['browser', 'dom', 'css!./emby-button', 'registerElement'], function (browser, dom) {
'use strict';
var EmbyButtonPrototype = Object.create(HTMLButtonElement.prototype); var EmbyButtonPrototype = Object.create(HTMLButtonElement.prototype);
@ -30,9 +31,8 @@
}, false); }, false);
} }
function animateButton(e) { function animateButton(e, btn) {
var btn = this;
requestAnimationFrame(function () { requestAnimationFrame(function () {
animateButtonInternal(e, btn); animateButtonInternal(e, btn);
}); });
@ -40,18 +40,23 @@
function onKeyDown(e) { function onKeyDown(e) {
if (e.keyCode == 13) { if (e.keyCode === 13) {
animateButton.call(this, e); animateButton(e, this);
} }
} }
function onMouseDown(e) { function onMouseDown(e) {
if (e.button == 0) { if (e.button === 0) {
animateButton.call(this, e); animateButton(e, this);
} }
} }
function onClick(e) {
animateButton(e, this);
}
function enableAnimation() { function enableAnimation() {
if (browser.tv) { if (browser.tv) {
// too slow // too slow
@ -77,7 +82,7 @@
passive: true passive: true
}); });
if (browser.safari) { if (browser.safari) {
dom.addEventListener(this, 'click', animateButton, { dom.addEventListener(this, 'click', onClick, {
passive: true passive: true
}); });
} else { } else {

View file

@ -1,4 +1,5 @@
define(['browser', 'dom', 'css!./emby-button', 'registerElement'], function (browser, dom) { define(['browser', 'dom', 'css!./emby-button', 'registerElement'], function (browser, dom) {
'use strict';
var EmbyButtonPrototype = Object.create(HTMLButtonElement.prototype); var EmbyButtonPrototype = Object.create(HTMLButtonElement.prototype);
@ -33,9 +34,8 @@
}, false); }, false);
} }
function animateButton(e) { function animateButton(e, btn) {
var btn = this;
requestAnimationFrame(function () { requestAnimationFrame(function () {
animateButtonInternal(e, btn); animateButtonInternal(e, btn);
}); });
@ -43,11 +43,16 @@
function onKeyDown(e) { function onKeyDown(e) {
if (e.keyCode == 13) { if (e.keyCode === 13) {
animateButton.call(this, e); animateButton(e, this);
} }
} }
function onClick(e) {
animateButton(e, this);
}
EmbyButtonPrototype.createdCallback = function () { EmbyButtonPrototype.createdCallback = function () {
if (this.classList.contains('paper-icon-button-light')) { if (this.classList.contains('paper-icon-button-light')) {
@ -60,7 +65,7 @@
dom.addEventListener(this, 'keydown', onKeyDown, { dom.addEventListener(this, 'keydown', onKeyDown, {
passive: true passive: true
}); });
dom.addEventListener(this, 'click', animateButton, { dom.addEventListener(this, 'click', onClick, {
passive: true passive: true
}); });
} }

View file

@ -2,7 +2,7 @@
position: relative; position: relative;
z-index: 1; z-index: 1;
vertical-align: middle; vertical-align: middle;
display: inline-flex; display: inline-block;
box-sizing: border-box; box-sizing: border-box;
width: 100%; width: 100%;
margin: 0; margin: 0;
@ -18,7 +18,18 @@
.checkboxContainer { .checkboxContainer {
margin-bottom: 1.8em; margin-bottom: 1.8em;
display: flex; display: block;
}
@supports (display: flex) {
.mdl-checkbox {
display: inline-flex;
}
.checkboxContainer {
display: flex;
}
} }
.checkboxContainer-withDescription { .checkboxContainer-withDescription {
@ -113,15 +124,17 @@
cursor: auto; cursor: auto;
} }
.checkboxList .mdl-checkbox { .checkboxList > .mdl-checkbox {
display: flex; display: flex;
margin: .5em 0; margin: .5em 0;
} }
.checkboxList-paperList { .checkboxList-paperList {
padding: 1em !important; padding: 1em !important;
margin: .75em 0 !important;
} }
.checkboxListLabel { .checkboxListLabel {
opacity: .7; opacity: .7;
} margin-bottom: 0;
}

View file

@ -1,11 +1,12 @@
define(['css!./emby-checkbox', 'registerElement'], function () { define(['css!./emby-checkbox', 'registerElement'], function () {
'use strict';
var EmbyCheckboxPrototype = Object.create(HTMLInputElement.prototype); var EmbyCheckboxPrototype = Object.create(HTMLInputElement.prototype);
function onKeyDown(e) { function onKeyDown(e) {
// Don't submit form on enter // Don't submit form on enter
if (e.keyCode == 13) { if (e.keyCode === 13) {
e.preventDefault(); e.preventDefault();
this.checked = !this.checked; this.checked = !this.checked;
@ -20,7 +21,7 @@
EmbyCheckboxPrototype.attachedCallback = function () { EmbyCheckboxPrototype.attachedCallback = function () {
if (this.getAttribute('data-embycheckbox') == 'true') { if (this.getAttribute('data-embycheckbox') === 'true') {
return; return;
} }

View file

@ -23,11 +23,16 @@
text-transform: none; text-transform: none;
border-bottom: 1px solid #333; border-bottom: 1px solid #333;
padding-left: .1em; padding-left: .1em;
background: transparent;
box-shadow: none;
} }
.emby-collapse-expandIcon { .emby-collapse-expandIcon {
transform-origin: 50% 50%; transform-origin: 50% 50%;
transition: transform 180ms ease-out; transition: transform 180ms ease-out;
position: absolute;
right: .5em;
font-size: 1.5em;
} }
.emby-collapse-expandIconExpanded { .emby-collapse-expandIconExpanded {

View file

@ -1,4 +1,5 @@
define(['browser', 'css!./emby-collapse', 'registerElement'], function (browser) { define(['browser', 'css!./emby-collapse', 'registerElement'], function (browser) {
'use strict';
var EmbyButtonPrototype = Object.create(HTMLDivElement.prototype); var EmbyButtonPrototype = Object.create(HTMLDivElement.prototype);
@ -9,7 +10,9 @@
elem.style.height = 'auto'; elem.style.height = 'auto';
var height = elem.offsetHeight + 'px'; var height = elem.offsetHeight + 'px';
elem.style.height = '0'; elem.style.height = '0';
elem.offsetHeight;
// trigger reflow
var newHeight = elem.offsetHeight;
elem.style.height = height; elem.style.height = height;
setTimeout(function () { setTimeout(function () {
@ -29,7 +32,8 @@
function slideUpToHide(button, elem) { function slideUpToHide(button, elem) {
elem.style.height = elem.offsetHeight + 'px'; elem.style.height = elem.offsetHeight + 'px';
elem.offsetHeight; // trigger reflow
var newHeight = elem.offsetHeight;
elem.classList.remove('expanded'); elem.classList.remove('expanded');
elem.style.height = '0'; elem.style.height = '0';
@ -49,14 +53,15 @@
function onButtonClick(e) { function onButtonClick(e) {
var collapseContent = this.parentNode.querySelector('.collapseContent'); var button = this;
var collapseContent = button.parentNode.querySelector('.collapseContent');
if (collapseContent.expanded) { if (collapseContent.expanded) {
collapseContent.expanded = false; collapseContent.expanded = false;
slideUpToHide(this, collapseContent); slideUpToHide(button, collapseContent);
} else { } else {
collapseContent.expanded = true; collapseContent.expanded = true;
slideDownToShow(this, collapseContent); slideDownToShow(button, collapseContent);
} }
} }
@ -75,10 +80,7 @@
var title = this.getAttribute('title'); var title = this.getAttribute('title');
var html = '<button is="emby-button" type="button" on-click="toggleExpand" id="expandButton" class="emby-collapsible-button iconRight">\ var html = '<button is="emby-button" type="button" on-click="toggleExpand" id="expandButton" class="emby-collapsible-button iconRight"><h3 class="emby-collapsible-title" title="' + title + '">' + title + '</h3><i class="md-icon emby-collapse-expandIcon">expand_more</i></button>';
<h3 class="emby-collapsible-title" title="' + title + '">' + title + '</h3>\
<i class="md-icon emby-collapse-expandIcon">expand_more</i>\
</button>';
this.insertAdjacentHTML('afterbegin', html); this.insertAdjacentHTML('afterbegin', html);
@ -86,7 +88,7 @@
button.addEventListener('click', onButtonClick); button.addEventListener('click', onButtonClick);
if (this.getAttribute('data-expanded') == 'true') { if (this.getAttribute('data-expanded') === 'true') {
onButtonClick.call(button); onButtonClick.call(button);
} }
}; };

View file

@ -3,7 +3,7 @@
margin: 0; margin: 0;
margin-bottom: 0 !important; margin-bottom: 0 !important;
background: none; background: none;
border: 1px solid rgb(221, 221, 221); border: 1px solid #383838;
border-width: 0 0 1px 0; border-width: 0 0 1px 0;
/* Prefixed box-sizing rules necessary for older browsers */ /* Prefixed box-sizing rules necessary for older browsers */
-webkit-box-sizing: border-box; -webkit-box-sizing: border-box;
@ -21,6 +21,8 @@
width: 100%; width: 100%;
background-color: transparent; background-color: transparent;
border-radius: 0; border-radius: 0;
/* Ensure it is over the label so that it can be clicked */
position: relative;
} }
.inputContainer { .inputContainer {

View file

@ -1,4 +1,5 @@
define(['layoutManager', 'browser', 'dom', 'css!./emby-input', 'registerElement'], function (layoutManager, browser, dom) { define(['layoutManager', 'browser', 'dom', 'css!./emby-input', 'registerElement'], function (layoutManager, browser, dom) {
'use strict';
var EmbyInputPrototype = Object.create(HTMLInputElement.prototype); var EmbyInputPrototype = Object.create(HTMLInputElement.prototype);
@ -19,7 +20,7 @@
bubbles: false, bubbles: false,
cancelable: false cancelable: false
})); }));
} };
Object.defineProperty(HTMLInputElement.prototype, 'value', descriptor); Object.defineProperty(HTMLInputElement.prototype, 'value', descriptor);
supportsFloatingLabel = true; supportsFloatingLabel = true;
@ -86,7 +87,7 @@
label.classList.remove('inputLabel-float'); label.classList.remove('inputLabel-float');
} else { } else {
var instanceSupportsFloat = supportsFloatingLabel && this.type != 'date' && this.type != 'time'; var instanceSupportsFloat = supportsFloatingLabel && this.type !== 'date' && this.type !== 'time';
if (instanceSupportsFloat) { if (instanceSupportsFloat) {
label.classList.add('inputLabel-float'); label.classList.add('inputLabel-float');

View file

@ -183,6 +183,57 @@
}); });
} }
function onTimerCreated(e, apiClient, data) {
var itemsContainer = this;
var programId = data.ProgramId;
// This could be null, not supported by all tv providers
var newTimerId = data.Id;
require(['cardBuilder'], function (cardBuilder) {
cardBuilder.onTimerCreated(programId, newTimerId, itemsContainer);
});
}
function onSeriesTimerCreated(e, apiClient, data) {
var itemsContainer = this;
}
function onTimerCancelled(e, apiClient, data) {
var itemsContainer = this;
var id = data.Id;
require(['cardBuilder'], function (cardBuilder) {
cardBuilder.onTimerCancelled(id, itemsContainer);
});
}
function onSeriesTimerCancelled(e, apiClient, data) {
var itemsContainer = this;
var id = data.Id;
require(['cardBuilder'], function (cardBuilder) {
cardBuilder.onSeriesTimerCancelled(id, itemsContainer);
});
}
function addNotificationEvent(instance, name, handler) {
var localHandler = handler.bind(instance);
events.on(serverNotifications, name, localHandler);
instance[name] = localHandler;
}
function removeNotificationEvent(instance, name) {
var handler = instance[name];
if (handler) {
events.off(serverNotifications, 'UserDataChanged', handler);
instance[name] = null;
}
}
ItemsContainerProtoType.attachedCallback = function () { ItemsContainerProtoType.attachedCallback = function () {
this.addEventListener('click', onClick); this.addEventListener('click', onClick);
@ -190,7 +241,9 @@
if (browser.touch) { if (browser.touch) {
this.addEventListener('contextmenu', disableEvent); this.addEventListener('contextmenu', disableEvent);
} else { } else {
this.addEventListener('contextmenu', onContextMenu); if (this.getAttribute('data-contextmenu') !== 'false') {
this.addEventListener('contextmenu', onContextMenu);
}
} }
if (layoutManager.desktop) { if (layoutManager.desktop) {
@ -203,9 +256,11 @@
itemShortcuts.on(this, getShortcutOptions()); itemShortcuts.on(this, getShortcutOptions());
var userDataHandler = onUserDataChanged.bind(this); addNotificationEvent(this, 'UserDataChanged', onUserDataChanged);
events.on(serverNotifications, 'UserDataChanged', userDataHandler); addNotificationEvent(this, 'TimerCreated', onTimerCreated);
this.userDataHandler = userDataHandler; addNotificationEvent(this, 'SeriesTimerCreated', onSeriesTimerCreated);
addNotificationEvent(this, 'TimerCancelled', onTimerCancelled);
addNotificationEvent(this, 'SeriesTimerCancelled', onSeriesTimerCancelled);
}; };
ItemsContainerProtoType.detachedCallback = function () { ItemsContainerProtoType.detachedCallback = function () {
@ -218,11 +273,11 @@
this.removeEventListener('contextmenu', disableEvent); this.removeEventListener('contextmenu', disableEvent);
itemShortcuts.off(this, getShortcutOptions()); itemShortcuts.off(this, getShortcutOptions());
var userDataHandler = this.userDataHandler; removeNotificationEvent(this, 'UserDataChanged');
if (userDataHandler) { removeNotificationEvent(this, 'TimerCreated');
events.off(serverNotifications, 'UserDataChanged', userDataHandler); removeNotificationEvent(this, 'SeriesTimerCreated');
this.userDataHandler = null; removeNotificationEvent(this, 'TimerCancelled');
} removeNotificationEvent(this, 'SeriesTimerCancelled');
}; };
document.registerElement('emby-itemscontainer', { document.registerElement('emby-itemscontainer', {

View file

@ -21,8 +21,9 @@
.mdl-radio__button { .mdl-radio__button {
line-height: 24px; line-height: 24px;
position: absolute; position: absolute;
width: 0; /* 1px is for focusing purposes, so the focusManager doesn't skip over it */
height: 0; width: 1px;
height: 1px;
margin: 0; margin: 0;
padding: 0; padding: 0;
opacity: 0; opacity: 0;
@ -43,13 +44,13 @@
height: 16px; height: 16px;
margin: 0; margin: 0;
cursor: pointer; cursor: pointer;
border: 2px solid rgba(0,0,0, 0.54); border: 2px solid currentcolor;
border-radius: 50%; border-radius: 50%;
z-index: 2; z-index: 2;
} }
.mdl-radio__button:checked + .mdl-radio__label + .mdl-radio__outer-circle { .mdl-radio__button:checked + .mdl-radio__label + .mdl-radio__outer-circle {
border: 2px solid rgb(63,81,181); border: 2px solid rgb(82, 181, 75);
} }
.mdl-radio__button:disabled + .mdl-radio__label + .mdl-radio__outer-circle { .mdl-radio__button:disabled + .mdl-radio__label + .mdl-radio__outer-circle {
@ -75,7 +76,7 @@
-webkit-transform: scale3d(0, 0, 0); -webkit-transform: scale3d(0, 0, 0);
transform: scale3d(0, 0, 0); transform: scale3d(0, 0, 0);
border-radius: 50%; border-radius: 50%;
background: rgb(63,81,181); background: rgb(82, 181, 75);
} }
.mdl-radio__button:checked + .mdl-radio__label + .mdl-radio__outer-circle + .mdl-radio__inner-circle { .mdl-radio__button:checked + .mdl-radio__label + .mdl-radio__outer-circle + .mdl-radio__inner-circle {
@ -89,7 +90,11 @@
} }
.mdl-radio__button:focus + .mdl-radio__label + .mdl-radio__outer-circle + .mdl-radio__inner-circle { .mdl-radio__button:focus + .mdl-radio__label + .mdl-radio__outer-circle + .mdl-radio__inner-circle {
box-shadow: 0 0 0px 10px rgba(0, 0, 0, 0.1); box-shadow: 0 0 0px 10px rgba(255, 255, 255, 0.76);
}
.mdl-radio__button:checked:focus + .mdl-radio__label + .mdl-radio__outer-circle + .mdl-radio__inner-circle {
box-shadow: 0 0 0px 10px rgba(82, 181, 75, 0.26);
} }
.mdl-radio__label { .mdl-radio__label {

View file

@ -1,11 +1,12 @@
define(['css!./emby-radio', 'registerElement'], function () { define(['css!./emby-radio', 'registerElement'], function () {
'use strict';
var EmbyRadioPrototype = Object.create(HTMLInputElement.prototype); var EmbyRadioPrototype = Object.create(HTMLInputElement.prototype);
function onKeyDown(e) { function onKeyDown(e) {
// Don't submit form on enter // Don't submit form on enter
if (e.keyCode == 13) { if (e.keyCode === 13) {
e.preventDefault(); e.preventDefault();
this.checked = true; this.checked = true;
@ -16,7 +17,7 @@
EmbyRadioPrototype.attachedCallback = function () { EmbyRadioPrototype.attachedCallback = function () {
if (this.getAttribute('data-radio') == 'true') { if (this.getAttribute('data-radio') === 'true') {
return; return;
} }

View file

@ -3,7 +3,7 @@
margin: 0; margin: 0;
margin-bottom: 0 !important; margin-bottom: 0 !important;
background: none; background: none;
border: 1px solid rgb(221, 221, 221); border: 1px solid #383838;
border-width: 0 0 1px 0; border-width: 0 0 1px 0;
/* Prefixed box-sizing rules necessary for older browsers */ /* Prefixed box-sizing rules necessary for older browsers */
-webkit-box-sizing: border-box; -webkit-box-sizing: border-box;

View file

@ -1,4 +1,5 @@
define(['layoutManager', 'browser', 'actionsheet', 'css!./emby-select', 'registerElement'], function (layoutManager, browser, actionsheet) { define(['layoutManager', 'browser', 'actionsheet', 'css!./emby-select', 'registerElement'], function (layoutManager, browser, actionsheet) {
'use strict';
var EmbySelectPrototype = Object.create(HTMLSelectElement.prototype); var EmbySelectPrototype = Object.create(HTMLSelectElement.prototype);
@ -54,7 +55,7 @@
function getLabel(select) { function getLabel(select) {
var elem = select.previousSibling; var elem = select.previousSibling;
while (elem && elem.tagName != 'LABEL') { while (elem && elem.tagName !== 'LABEL') {
elem = elem.previousSibling; elem = elem.previousSibling;
} }
return elem; return elem;

View file

@ -1,4 +1,5 @@
define(['browser', 'css!./emby-slider', 'registerElement', 'emby-input'], function (browser) { define(['browser', 'css!./emby-slider', 'registerElement', 'emby-input'], function (browser) {
'use strict';
var EmbySliderPrototype = Object.create(HTMLInputElement.prototype); var EmbySliderPrototype = Object.create(HTMLInputElement.prototype);
@ -28,9 +29,8 @@
}); });
} }
function updateBubble(range, bubble) { function updateBubble(range, value, bubble) {
var value = range.value;
bubble.style.left = (value - 1) + '%'; bubble.style.left = (value - 1) + '%';
if (range.getBubbleText) { if (range.getBubbleText) {
@ -41,7 +41,7 @@
EmbySliderPrototype.attachedCallback = function () { EmbySliderPrototype.attachedCallback = function () {
if (this.getAttribute('data-embycheckbox') == 'true') { if (this.getAttribute('data-embycheckbox') === 'true') {
return; return;
} }
@ -71,16 +71,26 @@
this.addEventListener('input', function (e) { this.addEventListener('input', function (e) {
this.dragging = true; this.dragging = true;
updateBubble(this, sliderBubble); });
this.addEventListener('change', function () {
this.dragging = false;
updateValues(this, backgroundLower, backgroundUpper);
});
this.addEventListener('mousemove', function (e) {
var rect = this.getBoundingClientRect();
var clientX = e.clientX;
var bubbleValue = (clientX - rect.left) / rect.width;
bubbleValue *= 100;
updateBubble(this, Math.round(bubbleValue), sliderBubble);
if (hasHideClass) { if (hasHideClass) {
sliderBubble.classList.remove('hide'); sliderBubble.classList.remove('hide');
hasHideClass = false; hasHideClass = false;
} }
}); });
this.addEventListener('change', function () { this.addEventListener('mouseleave', function () {
this.dragging = false;
updateValues(this, backgroundLower, backgroundUpper);
sliderBubble.classList.add('hide'); sliderBubble.classList.add('hide');
hasHideClass = true; hasHideClass = true;
}); });

View file

@ -1,5 +1,6 @@
.emby-tab-button { .emby-tab-button {
background: transparent; background: transparent;
box-shadow: none;
border: 2px solid transparent; border: 2px solid transparent;
border-width: 0 0 2px 0; border-width: 0 0 2px 0;
cursor: pointer; cursor: pointer;

View file

@ -1,4 +1,5 @@
define(['dom', 'scroller', 'browser', 'registerElement', 'css!./emby-tabs', 'scrollStyles'], function (dom, scroller, browser) { define(['dom', 'scroller', 'browser', 'registerElement', 'css!./emby-tabs', 'scrollStyles'], function (dom, scroller, browser) {
'use strict';
var EmbyTabs = Object.create(HTMLDivElement.prototype); var EmbyTabs = Object.create(HTMLDivElement.prototype);
var buttonClass = 'emby-tab-button'; var buttonClass = 'emby-tab-button';
@ -78,7 +79,7 @@
var onAnimationFinish = function () { var onAnimationFinish = function () {
//if (tabs.getAttribute('data-selectionbar') != 'false') { //if (tabs.getAttribute('data-selectionbar') !== 'false') {
// showButtonSelectionBar(newButton); // showButtonSelectionBar(newButton);
//} //}
newButton.classList.add(activeButtonClass); newButton.classList.add(activeButtonClass);
@ -103,7 +104,7 @@
var current = tabs.querySelector('.' + activeButtonClass); var current = tabs.querySelector('.' + activeButtonClass);
var tabButton = dom.parentWithClass(e.target, buttonClass); var tabButton = dom.parentWithClass(e.target, buttonClass);
if (tabButton && tabButton != current) { if (tabButton && tabButton !== current) {
if (current) { if (current) {
current.classList.remove(activeButtonClass); current.classList.remove(activeButtonClass);
@ -186,7 +187,7 @@
return; return;
} }
if (tabs.getAttribute('data-selectionbar') == 'false') { if (tabs.getAttribute('data-selectionbar') === 'false') {
return; return;
} }
@ -253,7 +254,7 @@
var tabButtons = tabs.querySelectorAll('.' + buttonClass); var tabButtons = tabs.querySelectorAll('.' + buttonClass);
if (current == selected || triggerEvent === false) { if (current === selected || triggerEvent === false) {
tabs.dispatchEvent(new CustomEvent("beforetabchange", { tabs.dispatchEvent(new CustomEvent("beforetabchange", {
detail: { detail: {
@ -269,7 +270,7 @@
var currentTabButton = tabButtons[current]; var currentTabButton = tabButtons[current];
moveSelectionBar(tabs, tabButtons[selected], currentTabButton, false); moveSelectionBar(tabs, tabButtons[selected], currentTabButton, false);
if (current != selected && currentTabButton) { if (current !== selected && currentTabButton) {
currentTabButton.classList.remove(activeButtonClass); currentTabButton.classList.remove(activeButtonClass);
} }

View file

@ -3,7 +3,7 @@
margin: 0; margin: 0;
margin-bottom: 0 !important; margin-bottom: 0 !important;
background: none; background: none;
border: 1px solid rgb(221, 221, 221); border: 1px solid #383838;
border-width: 0 0 1px 0; border-width: 0 0 1px 0;
/* Prefixed box-sizing rules necessary for older browsers */ /* Prefixed box-sizing rules necessary for older browsers */
-webkit-box-sizing: border-box; -webkit-box-sizing: border-box;

View file

@ -1,4 +1,5 @@
define(['layoutManager', 'browser', 'css!./emby-textarea', 'registerElement'], function (layoutManager, browser) { define(['layoutManager', 'browser', 'css!./emby-textarea', 'registerElement'], function (layoutManager, browser) {
'use strict';
function autoGrow(textarea, maxLines) { function autoGrow(textarea, maxLines) {
var self = this; var self = this;
@ -84,7 +85,7 @@
bubbles: false, bubbles: false,
cancelable: false cancelable: false
})); }));
} };
Object.defineProperty(HTMLTextAreaElement.prototype, 'value', descriptor); Object.defineProperty(HTMLTextAreaElement.prototype, 'value', descriptor);
supportsFloatingLabel = true; supportsFloatingLabel = true;
@ -113,7 +114,7 @@
label.innerHTML = this.getAttribute('label') || ''; label.innerHTML = this.getAttribute('label') || '';
label.classList.add('textareaLabel'); label.classList.add('textareaLabel');
if (!supportsFloatingLabel || this.type == 'date') { if (!supportsFloatingLabel || this.type === 'date') {
label.classList.add('nofloat'); label.classList.add('nofloat');
} }

View file

@ -0,0 +1,137 @@
.mdl-switch {
position: relative;
z-index: 1;
vertical-align: middle;
display: inline-flex;
align-items: center;
box-sizing: border-box;
width: 100%;
margin: 0;
padding: 0;
overflow: visible;
-webkit-touch-callout: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
flex-direction: row-reverse;
justify-content: flex-end;
}
.toggleContainer {
margin-bottom: 1.8em;
}
.mdl-switch__input {
width: 0;
height: 0;
margin: 0;
padding: 0;
opacity: 0;
-ms-appearance: none;
-moz-appearance: none;
-webkit-appearance: none;
appearance: none;
border: none;
}
.mdl-switch__trackContainer {
position: relative;
width: 2.9em;
}
.mdl-switch__track {
background: rgba(255,255,255, 0.26);
height: 1em;
border-radius: 1em;
cursor: pointer;
}
.mdl-switch__input:checked + .mdl-switch__label + .mdl-switch__trackContainer > .mdl-switch__track {
background: rgba(82,181,75, 0.5);
}
.mdl-switch__input.red:checked + .mdl-switch__label + .mdl-switch__trackContainer > .mdl-switch__track {
background: rgba(204,51,51, 0.5);
}
.mdl-switch__input[disabled] + .mdl-switch__label + .mdl-switch__trackContainer > .mdl-switch__track {
background: rgba(0,0,0, 0.12);
cursor: auto;
}
.mdl-switch__thumb {
background: #999;
position: absolute;
left: 0;
top: -.25em;
height: 1.44em;
width: 1.44em;
border-radius: 50%;
cursor: pointer;
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
transition-duration: 0.28s;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-property: left;
display: flex;
align-items: center;
justify-content: center;
}
.mdl-switch__input:checked + .mdl-switch__label + .mdl-switch__trackContainer > .mdl-switch__thumb {
background: rgb(82,181,75);
left: 1.466em;
box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.14), 0 3px 3px -2px rgba(0, 0, 0, 0.2), 0 1px 8px 0 rgba(0, 0, 0, 0.12);
}
.mdl-switch__input.red:checked + .mdl-switch__label + .mdl-switch__trackContainer > .mdl-switch__thumb {
background: rgb(204,51,51);
box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.14), 0 3px 3px -2px rgba(0, 0, 0, 0.2), 0 1px 8px 0 rgba(0, 0, 0, 0.12);
}
.mdl-switch__input[disabled] + .mdl-switch__label + .mdl-switch__trackContainer > .mdl-switch__thumb {
background: rgb(189,189,189);
cursor: auto;
}
.mdl-switch__focus-helper {
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
display: inline-block;
box-sizing: border-box;
width: .6em;
height: .6em;
border-radius: 50%;
background-color: transparent;
}
.mdl-switch__input:focus + .mdl-switch__label + .mdl-switch__trackContainer .mdl-switch__focus-helper {
box-shadow: 0 0 0px 20px rgba(255,255,255, 0.26);
background-color: rgba(255,255,255, 0.26);
}
.mdl-switch__input:checked:focus + .mdl-switch__label + .mdl-switch__trackContainer .mdl-switch__focus-helper {
box-shadow: 0 0 0px 20px rgba(82,181,75, 0.26);
background-color: rgba(82,181,75, 0.26);
}
.mdl-switch__input.red:checked:focus + .mdl-switch__label + .mdl-switch__trackContainer .mdl-switch__focus-helper {
box-shadow: 0 0 0px 20px rgba(204,51,51, 0.26);
background-color: rgba(204,51,51, 0.26);
}
.mdl-switch__label {
cursor: pointer;
margin: 0;
display: inline-flex;
align-items: center;
margin-left: .7em;
}
.mdl-switch__input[disabled] .mdl-switch__label {
color: rgb(189,189,189);
cursor: auto;
}

View file

@ -0,0 +1,50 @@
define(['css!./emby-toggle', 'registerElement'], function () {
'use strict';
var EmbyTogglePrototype = Object.create(HTMLInputElement.prototype);
function onKeyDown(e) {
// Don't submit form on enter
if (e.keyCode === 13) {
e.preventDefault();
this.checked = !this.checked;
this.dispatchEvent(new CustomEvent('change', {
bubbles: true
}));
return false;
}
}
EmbyTogglePrototype.attachedCallback = function () {
if (this.getAttribute('data-embytoggle') === 'true') {
return;
}
this.setAttribute('data-embytoggle', 'true');
this.classList.add('mdl-switch__input');
var labelElement = this.parentNode;
labelElement.classList.add('mdl-switch');
labelElement.classList.add('mdl-js-switch');
var labelTextElement = labelElement.querySelector('span');
labelElement.insertAdjacentHTML('beforeend', '<div class="mdl-switch__trackContainer"><div class="mdl-switch__track"></div><div class="mdl-switch__thumb"><span class="mdl-switch__focus-helper"></span></div></div>');
labelTextElement.classList.add('toggleButtonLabel');
labelTextElement.classList.add('mdl-switch__label');
this.addEventListener('keydown', onKeyDown);
};
document.registerElement('emby-toggle', {
prototype: EmbyTogglePrototype,
extends: 'input'
});
});

View file

@ -1,10 +1,11 @@
define([], function () { define([], function () {
'use strict';
function getFetchPromise(request) { function getFetchPromise(request) {
var headers = request.headers || {}; var headers = request.headers || {};
if (request.dataType == 'json') { if (request.dataType === 'json') {
headers.accept = 'application/json'; headers.accept = 'application/json';
} }
@ -107,9 +108,9 @@
if (response.status < 400) { if (response.status < 400) {
if (request.dataType == 'json' || request.headers.accept == 'application/json') { if (request.dataType === 'json' || request.headers.accept === 'application/json') {
return response.json(); return response.json();
} else if (request.dataType == 'text' || (response.headers.get('Content-Type') || '').toLowerCase().indexOf('text/') == 0) { } else if (request.dataType === 'text' || (response.headers.get('Content-Type') || '').toLowerCase().indexOf('text/') === 0) {
return response.text(); return response.text();
} else { } else {
return response; return response;

View file

@ -1,4 +1,5 @@
define(['dom'], function (dom) { define(['dom'], function (dom) {
'use strict';
var scopes = []; var scopes = [];
function pushScope(elem) { function pushScope(elem) {
@ -48,7 +49,7 @@ define(['dom'], function (dom) {
var focusableContainerTagNames = ['BODY', 'DIALOG']; var focusableContainerTagNames = ['BODY', 'DIALOG'];
var focusableQuery = focusableTagNames.map(function (t) { var focusableQuery = focusableTagNames.map(function (t) {
if (t == 'INPUT') { if (t === 'INPUT') {
t += ':not([type="range"])'; t += ':not([type="range"])';
} }
return t + ':not([tabindex="-1"]):not(:disabled)'; return t + ':not([tabindex="-1"]):not(:disabled)';
@ -57,7 +58,7 @@ define(['dom'], function (dom) {
function isFocusable(elem) { function isFocusable(elem) {
if (focusableTagNames.indexOf(elem.tagName) != -1) { if (focusableTagNames.indexOf(elem.tagName) !== -1) {
return true; return true;
} }
@ -99,13 +100,13 @@ define(['dom'], function (dom) {
return false; return false;
} }
if (elem.getAttribute('tabindex') == "-1") { if (elem.getAttribute('tabindex') === "-1") {
return false; return false;
} }
if (elem.tagName == 'INPUT') { if (elem.tagName === 'INPUT') {
var type = elem.type; var type = elem.type;
if (type == 'range') { if (type === 'range') {
return false; return false;
} }
} }
@ -139,7 +140,7 @@ define(['dom'], function (dom) {
function isFocusContainer(elem, direction) { function isFocusContainer(elem, direction) {
if (focusableContainerTagNames.indexOf(elem.tagName) != -1) { if (focusableContainerTagNames.indexOf(elem.tagName) !== -1) {
return true; return true;
} }
if (elem.classList.contains('focuscontainer')) { if (elem.classList.contains('focuscontainer')) {
@ -151,7 +152,7 @@ define(['dom'], function (dom) {
return true; return true;
} }
} }
else if (direction == 3) { else if (direction === 3) {
if (elem.classList.contains('focuscontainer-down')) { if (elem.classList.contains('focuscontainer-down')) {
return true; return true;
} }
@ -230,11 +231,11 @@ define(['dom'], function (dom) {
for (var i = 0, length = focusable.length; i < length; i++) { for (var i = 0, length = focusable.length; i < length; i++) {
var curr = focusable[i]; var curr = focusable[i];
if (curr == activeElement) { if (curr === activeElement) {
continue; continue;
} }
// Don't refocus into the same container // Don't refocus into the same container
if (curr == focusableContainer) { if (curr === focusableContainer) {
continue; continue;
} }
@ -256,7 +257,7 @@ define(['dom'], function (dom) {
if (elementRect.left >= rect.left) { if (elementRect.left >= rect.left) {
continue; continue;
} }
if (elementRect.right == rect.right) { if (elementRect.right === rect.right) {
continue; continue;
} }
break; break;
@ -265,7 +266,7 @@ define(['dom'], function (dom) {
if (elementRect.right <= rect.right) { if (elementRect.right <= rect.right) {
continue; continue;
} }
if (elementRect.left == rect.left) { if (elementRect.left === rect.left) {
continue; continue;
} }
break; break;
@ -304,8 +305,8 @@ define(['dom'], function (dom) {
// See if there's a focusable container, and if so, send the focus command to that // See if there's a focusable container, and if so, send the focus command to that
var nearestElementFocusableParent = dom.parentWithClass(nearestElement, 'focusable'); var nearestElementFocusableParent = dom.parentWithClass(nearestElement, 'focusable');
if (nearestElementFocusableParent && nearestElementFocusableParent != nearestElement && activeElement) { if (nearestElementFocusableParent && nearestElementFocusableParent !== nearestElement && activeElement) {
if (dom.parentWithClass(activeElement, 'focusable') != nearestElementFocusableParent) { if (dom.parentWithClass(activeElement, 'focusable') !== nearestElementFocusableParent) {
nearestElement = nearestElementFocusableParent; nearestElement = nearestElementFocusableParent;
} }
} }
@ -404,12 +405,12 @@ define(['dom'], function (dom) {
function sortNodesT(a, b) { function sortNodesT(a, b) {
var result = a.distT - b.distT; var result = a.distT - b.distT;
if (result != 0) { if (result !== 0) {
return result; return result;
} }
result = a.index - b.index; result = a.index - b.index;
if (result != 0) { if (result !== 0) {
return result; return result;
} }

View file

@ -15,6 +15,10 @@
background-color: #222326; background-color: #222326;
} }
.formDialogHeader-clear, .formDialogFooter-clear {
background-color: transparent;
}
.formDialogHeaderTitle { .formDialogHeaderTitle {
margin-left: .25em; margin-left: .25em;
/* In case of h1, h2, h3 */ /* In case of h1, h2, h3 */
@ -27,7 +31,7 @@
} }
.dialogContentInner { .dialogContentInner {
padding: .5em 1.5em 20em 1.5em; padding: .5em 1em 20em 1em;
} }
.dialogContentInner-mini { .dialogContentInner-mini {
@ -49,11 +53,16 @@
left: 0; left: 0;
right: 0; right: 0;
display: flex; display: flex;
padding: 1.5em; padding: 1.25em 1em;
/* Without this emby-checkbox is able to appear on top */ /* Without this emby-checkbox is able to appear on top */
z-index: 1; z-index: 1;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
flex-wrap: wrap;
}
.formDialogFooter-flex {
position: static;
} }
.formDialogFooterItem { .formDialogFooterItem {
@ -61,6 +70,14 @@
margin-right: .5em !important; margin-right: .5em !important;
flex-grow: 1; flex-grow: 1;
text-align: center; text-align: center;
flex-basis: 0;
}
.formDialogFooterItem-autosize {
flex-basis: initial;
flex-grow: initial;
padding-left: 2em;
padding-right: 2em;
} }
@media all and (min-width: 800px) { @media all and (min-width: 800px) {
@ -68,6 +85,11 @@
.formDialogFooterItem { .formDialogFooterItem {
max-width: 80%; max-width: 80%;
} }
.dialogContentInner {
padding-left: 1.5em;
padding-right: 1.5em;
}
} }
@media all and (min-width: 1280px) { @media all and (min-width: 1280px) {

View file

@ -1,4 +1,5 @@
define(['connectionManager', 'userSettings', 'events'], function (connectionManager, userSettings, events) { define(['connectionManager', 'userSettings', 'events'], function (connectionManager, userSettings, events) {
'use strict';
var allTranslations = {}; var allTranslations = {};
var currentCulture; var currentCulture;
@ -69,20 +70,20 @@ define(['connectionManager', 'userSettings', 'events'], function (connectionMana
// If it's de-DE, convert to just de // If it's de-DE, convert to just de
var parts = culture.split('-'); var parts = culture.split('-');
if (parts.length == 2) { if (parts.length === 2) {
if (parts[0].toLowerCase() == parts[1].toLowerCase()) { if (parts[0].toLowerCase() === parts[1].toLowerCase()) {
culture = parts[0].toLowerCase(); culture = parts[0].toLowerCase();
} }
} }
var lower = culture.toLowerCase(); var lower = culture.toLowerCase();
if (lower == 'ca-es') { if (lower === 'ca-es') {
return 'ca'; return 'ca';
} }
// normalize Swedish // normalize Swedish
if (lower == 'sv-se') { if (lower === 'sv-se') {
return 'sv'; return 'sv';
} }
@ -130,12 +131,12 @@ define(['connectionManager', 'userSettings', 'events'], function (connectionMana
lang = normalizeLocaleName(lang); lang = normalizeLocaleName(lang);
var filtered = translations.filter(function (t) { var filtered = translations.filter(function (t) {
return normalizeLocaleName(t.lang) == lang; return normalizeLocaleName(t.lang) === lang;
}); });
if (!filtered.length) { if (!filtered.length) {
filtered = translations.filter(function (t) { filtered = translations.filter(function (t) {
return normalizeLocaleName(t.lang) == 'en-us'; return normalizeLocaleName(t.lang) === 'en-us';
}); });
} }
@ -148,7 +149,7 @@ define(['connectionManager', 'userSettings', 'events'], function (connectionMana
var url = filtered[0].path; var url = filtered[0].path;
url += url.indexOf('?') == -1 ? '?' : '&'; url += url.indexOf('?') === -1 ? '?' : '&';
url += 'v=' + cacheParam; url += 'v=' + cacheParam;
var xhr = new XMLHttpRequest(); var xhr = new XMLHttpRequest();
@ -217,14 +218,14 @@ define(['connectionManager', 'userSettings', 'events'], function (connectionMana
var startIndex = html.indexOf('${'); var startIndex = html.indexOf('${');
if (startIndex == -1) { if (startIndex === -1) {
return html; return html;
} }
startIndex += 2; startIndex += 2;
var endIndex = html.indexOf('}', startIndex); var endIndex = html.indexOf('}', startIndex);
if (endIndex == -1) { if (endIndex === -1) {
return html; return html;
} }
@ -250,7 +251,7 @@ define(['connectionManager', 'userSettings', 'events'], function (connectionMana
events.on(connectionManager, 'localusersignedin', updateCurrentCulture); events.on(connectionManager, 'localusersignedin', updateCurrentCulture);
events.on(userSettings, 'change', function (e, name) { events.on(userSettings, 'change', function (e, name) {
if (name == 'language') { if (name === 'language') {
updateCurrentCulture(); updateCurrentCulture();
} }
}); });

View file

@ -0,0 +1,106 @@
define(['dialogHelper', 'globalize', 'userSettings', 'layoutManager', 'connectionManager', 'require', 'loading', 'scrollHelper', 'emby-checkbox', 'css!./../formdialog', 'material-icons'], function (dialogHelper, globalize, userSettings, layoutManager, connectionManager, require, loading, scrollHelper) {
'use strict';
function save(context, options) {
var categories = [];
var chkCategorys = context.querySelectorAll('.chkCategory');
for (var i = 0, length = chkCategorys.length; i < length; i++) {
var type = chkCategorys[i].getAttribute('data-type');
if (chkCategorys[i].checked) {
categories.push(type);
}
}
if (categories.length >= 4) {
categories.push('series');
}
// differentiate between none and all
categories.push('all');
options.categories = categories;
}
function load(context, options) {
var selectedCategories = options.categories || [];
var chkCategorys = context.querySelectorAll('.chkCategory');
for (var i = 0, length = chkCategorys.length; i < length; i++) {
var type = chkCategorys[i].getAttribute('data-type');
chkCategorys[i].checked = !selectedCategories.length || selectedCategories.indexOf(type) !== -1;
}
}
function showEditor(options) {
return new Promise(function (resolve, reject) {
var settingsChanged = false;
require(['text!./guide-categories.template.html'], function (template) {
var dialogOptions = {
removeOnClose: true,
scrollY: false
};
if (layoutManager.tv) {
dialogOptions.size = 'fullscreen';
} else {
dialogOptions.size = 'small';
}
var dlg = dialogHelper.createDialog(dialogOptions);
dlg.classList.add('formDialog');
var html = '';
html += globalize.translateDocument(template, 'sharedcomponents');
dlg.innerHTML = html;
dlg.addEventListener('change', function () {
settingsChanged = true;
});
dlg.addEventListener('close', function () {
if (layoutManager.tv) {
scrollHelper.centerFocus.off(dlg.querySelector('.formDialogContent'), false);
}
save(dlg, options);
if (settingsChanged) {
resolve(options);
} else {
reject();
}
});
dlg.querySelector('.btnCancel').addEventListener('click', function () {
dialogHelper.close(dlg);
});
if (layoutManager.tv) {
scrollHelper.centerFocus.on(dlg.querySelector('.formDialogContent'), false);
}
load(dlg, options);
dialogHelper.open(dlg);
});
});
}
return {
show: showEditor
};
});

View file

@ -0,0 +1,29 @@
<div class="formDialogHeader">
<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><i class="md-icon">&#xE5C4;</i></button>
<h3 class="formDialogHeaderTitle">
${Categories}
</h3>
</div>
<div class="formDialogContent smoothScrollY">
<form class="dialogContentInner dialog-content-centered" style="padding-top:2em;">
<div class="checkboxList">
<label>
<input type="checkbox" is="emby-checkbox" class="chkCategory" data-type="movies" />
<span>${Movies}</span>
</label>
<label>
<input type="checkbox" is="emby-checkbox" class="chkCategory" data-type="sports" />
<span>${Sports}</span>
</label>
<label>
<input type="checkbox" is="emby-checkbox" class="chkCategory" data-type="kids" />
<span>${Kids}</span>
</label>
<label>
<input type="checkbox" is="emby-checkbox" class="chkCategory" data-type="news" />
<span>${News}</span>
</label>
</div>
</form>
</div>

View file

@ -1,27 +1,66 @@
define(['dialogHelper', 'globalize', 'userSettings', 'layoutManager', 'connectionManager', 'require', 'loading', 'scrollHelper', 'emby-checkbox', 'css!./../formdialog', 'material-icons'], function (dialogHelper, globalize, userSettings, layoutManager, connectionManager, require, loading, scrollHelper) { define(['dialogHelper', 'globalize', 'userSettings', 'layoutManager', 'connectionManager', 'require', 'loading', 'scrollHelper', 'emby-checkbox', 'emby-radio', 'css!./../formdialog', 'material-icons'], function (dialogHelper, globalize, userSettings, layoutManager, connectionManager, require, loading, scrollHelper) {
'use strict';
function save(context) { function save(context) {
var i, length;
var chkIndicators = context.querySelectorAll('.chkIndicator'); var chkIndicators = context.querySelectorAll('.chkIndicator');
for (var i = 0, length = chkIndicators.length; i < length; i++) { for (i = 0, length = chkIndicators.length; i < length; i++) {
var type = chkIndicators[i].getAttribute('data-type'); var type = chkIndicators[i].getAttribute('data-type');
userSettings.set('guide-indicator-' + type, chkIndicators[i].checked); userSettings.set('guide-indicator-' + type, chkIndicators[i].checked);
}
userSettings.set('guide-colorcodedbackgrounds', context.querySelector('.chkColorCodedBackgrounds').checked);
userSettings.set('livetv-favoritechannelsattop', context.querySelector('.chkFavoriteChannelsAtTop').checked);
var sortBys = context.querySelectorAll('.chkSortOrder');
for (i = 0, length = sortBys.length; i < length; i++) {
if (sortBys[i].checked) {
userSettings.set('livetv-channelorder', sortBys[i].value);
break;
}
} }
} }
function load(context) { function load(context) {
var i, length;
var chkIndicators = context.querySelectorAll('.chkIndicator'); var chkIndicators = context.querySelectorAll('.chkIndicator');
for (var i = 0, length = chkIndicators.length; i < length; i++) { for (i = 0, length = chkIndicators.length; i < length; i++) {
var type = chkIndicators[i].getAttribute('data-type'); var type = chkIndicators[i].getAttribute('data-type');
if (chkIndicators[i].getAttribute('data-default') == 'true') { if (chkIndicators[i].getAttribute('data-default') === 'true') {
chkIndicators[i].checked = userSettings.get('guide-indicator-' + type) != 'false'; chkIndicators[i].checked = userSettings.get('guide-indicator-' + type) !== 'false';
} else { } else {
chkIndicators[i].checked = userSettings.get('guide-indicator-' + type) == 'true'; chkIndicators[i].checked = userSettings.get('guide-indicator-' + type) === 'true';
}
}
context.querySelector('.chkColorCodedBackgrounds').checked = userSettings.get('guide-colorcodedbackgrounds') === 'true';
context.querySelector('.chkFavoriteChannelsAtTop').checked = userSettings.get('livetv-favoritechannelsattop') !== 'false';
var sortByValue = userSettings.get('livetv-channelorder') || 'DatePlayed';
var sortBys = context.querySelectorAll('.chkSortOrder');
for (i = 0, length = sortBys.length; i < length; i++) {
sortBys[i].checked = sortBys[i].value === sortByValue;
}
}
function onSortByChange() {
var newValue = this.value;
if (this.checked) {
var changed = options.query.SortBy !== newValue;
options.query.SortBy = newValue.replace('_', ',');
options.query.StartIndex = 0;
if (options.callback && changed) {
options.callback();
} }
} }
} }

View file

@ -7,6 +7,14 @@
<div class="formDialogContent smoothScrollY"> <div class="formDialogContent smoothScrollY">
<form class="dialogContentInner dialog-content-centered" style="padding-top:2em;"> <form class="dialogContentInner dialog-content-centered" style="padding-top:2em;">
<h3 class="checkboxListLabel">${SortChannelsBy}</h3>
<label class="radio-label-block"><input type="radio" is="emby-radio" name="ChannelSortOrder" value="Number" class="chkSortOrder" /><span>${ChannelNumber}</span></label>
<label class="radio-label-block"><input type="radio" is="emby-radio" name="ChannelSortOrder" value="DatePlayed" class="chkSortOrder" /><span>${RecentlyWatched}</span></label>
<br />
<label class="checkboxContainer">
<input type="checkbox" is="emby-checkbox" class="chkFavoriteChannelsAtTop" />
<span>${PlaceFavoriteChannelsAtBeginning}</span>
</label>
<h3 class="checkboxListLabel">${ShowIndicatorsFor}</h3> <h3 class="checkboxListLabel">${ShowIndicatorsFor}</h3>
<div class="checkboxList"> <div class="checkboxList">
<label> <label>
@ -30,5 +38,10 @@
<span>${RepeatEpisodes}</span> <span>${RepeatEpisodes}</span>
</label> </label>
</div> </div>
<br />
<label class="checkboxContainer">
<input type="checkbox" is="emby-checkbox" class="chkColorCodedBackgrounds" />
<span>${EnableColorCodedBackgrounds}</span>
</label>
</form> </form>
</div> </div>

View file

@ -8,6 +8,8 @@
white-space: nowrap; white-space: nowrap;
width: 100%; width: 100%;
flex-shrink: 0; flex-shrink: 0;
display: flex;
padding-left: 3.4em;
} }
.tvProgramSectionHeader { .tvProgramSectionHeader {
@ -21,34 +23,10 @@
position: relative; position: relative;
} }
.tvProgramTimeSlotInner {
padding: .5em;
}
.tvProgramInfo {
vertical-align: middle;
padding: .5em .5em;
border-bottom: .65vh solid #121212;
}
.tvProgramCurrentTimeSlot {
background-color: green;
}
.tvProgramName {
color: #fff;
margin-bottom: .5em;
}
.tvProgramTime {
color: #fff;
}
.guideProgramIndicator { .guideProgramIndicator {
text-transform: uppercase; text-transform: uppercase;
border-radius: 2px; border-radius: 2px;
margin-right: .5em; margin-right: .5em;
color: #fff;
font-size: 74%; font-size: 74%;
padding: .2em .25em; padding: .2em .25em;
display: inline-flex; display: inline-flex;
@ -58,48 +36,8 @@
color: #fff; color: #fff;
} }
.newTvProgram {
background: #64A239;
}
.liveTvProgram {
background: #EC407A;
}
.premiereTvProgram {
background: #EF6C00;
}
.repeatTvProgram {
background: #009688;
}
.programAccent {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 2px;
}
.sportsAccent {
background-color: #0A7C33;
}
.newsAccent {
background-color: #523378;
}
.movieAccent {
background-color: #A43913;
}
.childAccent {
background-color: #0B487D;
}
.channelTimeslotHeader { .channelTimeslotHeader {
float: left; flex-shrink: 0;
} }
.timeslotHeaders { .timeslotHeaders {
@ -109,15 +47,14 @@
.programContainer { .programContainer {
white-space: nowrap; white-space: nowrap;
position: relative; position: relative;
} display: flex;
align-items: flex-start;
.programGridContainer {
margin-left: 12.2vw;
} }
.channelPrograms { .channelPrograms {
white-space: nowrap; white-space: nowrap;
position: relative; position: relative;
contain: strict;
} }
.timeslotHeadersInner { .timeslotHeadersInner {
@ -200,7 +137,6 @@
background: rgba(40, 40, 40, .9); background: rgba(40, 40, 40, .9);
display: flex; display: flex;
align-items: center; align-items: center;
color: #fff !important;
text-decoration: none; text-decoration: none;
/* Needed in firefox */ /* Needed in firefox */
text-align: left; text-align: left;
@ -281,7 +217,7 @@
.channelHeaderCell { .channelHeaderCell {
border-bottom: .65vh solid #121212 !important; border-bottom: .65vh solid #121212 !important;
background-size: auto 70%; background-size: auto 70%;
background-position: 90% center; background-position: 92% center;
background-repeat: no-repeat; background-repeat: no-repeat;
} }
@ -301,6 +237,12 @@
.channelPrograms, .channelHeaderCell { .channelPrograms, .channelHeaderCell {
height: 4em; height: 4em;
contain: strict;
}
.channelPrograms {
display: flex;
flex-direction: column;
} }
.channelPrograms-tv, .channelHeaderCell-tv { .channelPrograms-tv, .channelHeaderCell-tv {
@ -319,14 +261,6 @@
height: 3em; height: 3em;
} }
.pointerInput .channelHeaderCell:hover {
background-color: #444;
}
.channelList {
float: left;
}
.programGrid { .programGrid {
padding-bottom: 4px; padding-bottom: 4px;
} }
@ -343,7 +277,6 @@
border-left: .65vh solid #121212 !important; border-left: .65vh solid #121212 !important;
background-color: rgba(32, 32, 32, .95); background-color: rgba(32, 32, 32, .95);
display: flex; display: flex;
color: #fff !important;
text-decoration: none; text-decoration: none;
overflow: hidden; overflow: hidden;
align-items: center; align-items: center;
@ -352,15 +285,32 @@
contain: strict; contain: strict;
} }
.timeslotCellInner { .programAccent {
position: absolute; position: absolute;
bottom: 0; bottom: 0;
overflow: hidden; left: 0;
width: 100%; right: 0;
top: 0; height: 2px;
display: block; }
text-decoration: none;
color: #fff !important; .sportsAccent {
background-color: #3949AB;
}
.movieAccent {
background-color: #5E35B1;
}
.childAccent {
background-color: #039BE5;
}
.newsAccent {
background-color: #43A047;
}
.specialsAccent {
background-color: #FB8C00;
} }
.guideProgramName { .guideProgramName {
@ -371,11 +321,6 @@
align-items: center; align-items: center;
} }
.guideProgramTime {
padding: 0 .5em .35em;
color: #bbb;
}
.programIcon { .programIcon {
margin-left: auto; margin-left: auto;
margin-right: .25em; margin-right: .25em;
@ -419,8 +364,41 @@
} }
} }
.channelsContainer {
display: flex;
flex-shrink: 0;
}
.btnCategories {
margin: 0 .3em 0 .5em !important;
padding: 0 !important;
flex-shrink: 0;
background: rgba(40, 40, 40, .9);
border-radius: 0 !important;
width: 2.6em;
font-weight: normal !important;
position: relative;
}
.btnCategoriesText {
transform: rotate(90deg);
text-transform: uppercase;
transform-origin: left;
margin-left: 1.2em;
letter-spacing: .25em;
position: absolute;
top: 0;
margin-top: 1em;
white-space: nowrap;
}
.channelList {
display: flex;
flex-direction: column;
}
.channelList, .programGrid { .channelList, .programGrid {
height: auto !important; contain: layout style;
} }
.programCell, .channelHeaderCell, .btnSelectDate { .programCell, .channelHeaderCell, .btnSelectDate {
@ -435,6 +413,11 @@
color: #cc3333 !important; color: #cc3333 !important;
} }
.seriesTimerIcon-inactive {
color: inherit !important;
opacity: .7;
}
.visibleGuideScroller::-webkit-scrollbar { .visibleGuideScroller::-webkit-scrollbar {
width: 10px; width: 10px;
height: 10px; height: 10px;
@ -460,3 +443,14 @@
display: flex; display: flex;
align-items: center; align-items: center;
} }
@media all and (max-width: 800px), all and (max-height: 600px) {
.tvGuideHeader {
padding-left: 0;
}
.btnCategories {
display: none;
}
}

View file

@ -1,4 +1,5 @@
define(['require', 'browser', 'globalize', 'connectionManager', 'serverNotifications', 'loading', 'datetime', 'focusManager', 'userSettings', 'imageLoader', 'events', 'layoutManager', 'itemShortcuts', 'registrationservices', 'dom', 'clearButtonStyle', 'css!./guide.css', 'material-icons', 'scrollStyles', 'emby-button', 'paper-icon-button-light'], function (require, browser, globalize, connectionManager, serverNotifications, loading, datetime, focusManager, userSettings, imageLoader, events, layoutManager, itemShortcuts, registrationServices, dom) { define(['require', 'browser', 'globalize', 'connectionManager', 'serverNotifications', 'loading', 'datetime', 'focusManager', 'userSettings', 'imageLoader', 'events', 'layoutManager', 'itemShortcuts', 'registrationservices', 'dom', 'clearButtonStyle', 'css!./guide.css', 'programStyles', 'material-icons', 'scrollStyles', 'emby-button', 'paper-icon-button-light'], function (require, browser, globalize, connectionManager, serverNotifications, loading, datetime, focusManager, userSettings, imageLoader, events, layoutManager, itemShortcuts, registrationServices, dom) {
'use strict';
function showViewSettings(instance) { function showViewSettings(instance) {
@ -9,12 +10,24 @@
}); });
} }
function showCategoryOptions(instance) {
require(['guide-categories-dialog'], function (guideCategoriesDialog) {
guideCategoriesDialog.show(instance.categoryOptions).then(function (categoryOptions) {
instance.categoryOptions = categoryOptions;
instance.refresh();
});
});
}
function Guide(options) { function Guide(options) {
var self = this; var self = this;
var items = {}; var items = {};
self.options = options; self.options = options;
self.categoryOptions = { categories: [] };
// 30 mins // 30 mins
var cellCurationMinutes = 30; var cellCurationMinutes = 30;
@ -26,14 +39,6 @@
var currentStartIndex = 0; var currentStartIndex = 0;
var currentChannelLimit = 0; var currentChannelLimit = 0;
var channelQuery = {
StartIndex: 0,
EnableFavoriteSorting: true
};
var channelsPromise;
self.refresh = function () { self.refresh = function () {
currentDate = null; currentDate = null;
@ -151,6 +156,12 @@
var apiClient = connectionManager.currentApiClient(); var apiClient = connectionManager.currentApiClient();
var channelQuery = {
StartIndex: 0,
EnableFavoriteSorting: userSettings.get('livetv-favoritechannelsattop') !== 'false'
};
channelQuery.UserId = apiClient.getCurrentUserId(); channelQuery.UserId = apiClient.getCurrentUserId();
getChannelLimit(context).then(function (channelLimit) { getChannelLimit(context).then(function (channelLimit) {
@ -165,7 +176,44 @@
channelQuery.EnableUserData = false; channelQuery.EnableUserData = false;
channelQuery.EnableImageTypes = "Primary"; channelQuery.EnableImageTypes = "Primary";
channelsPromise = channelsPromise || apiClient.getLiveTvChannels(channelQuery); var categories = self.categoryOptions.categories || [];
var displayMovieContent = !categories.length || categories.indexOf('movies') !== -1;
var displaySportsContent = !categories.length || categories.indexOf('sports') !== -1;
var displayNewsContent = !categories.length || categories.indexOf('news') !== -1;
var displayKidsContent = !categories.length || categories.indexOf('kids') !== -1;
var displaySeriesContent = !categories.length || categories.indexOf('series') !== -1;
if (displayMovieContent && displaySportsContent && displayNewsContent && displayKidsContent) {
channelQuery.IsMovie = null;
channelQuery.IsSports = null;
channelQuery.IsKids = null;
channelQuery.IsNews = null;
channelQuery.IsSeries = null;
} else {
if (displayNewsContent) {
channelQuery.IsNews = true;
}
if (displaySportsContent) {
channelQuery.IsSports = true;
}
if (displayKidsContent) {
channelQuery.IsKids = true;
}
if (displayMovieContent) {
channelQuery.IsMovie = true;
}
if (displaySeriesContent) {
channelQuery.IsSeries = true;
}
}
if (userSettings.get('livetv-channelorder') === 'Number') {
channelQuery.SortBy = "SortName";
channelQuery.SortOrder = "Ascending";
} else {
channelQuery.SortBy = "DatePlayed";
channelQuery.SortOrder = "Descending";
}
var date = newStartDate; var date = newStartDate;
// Add one second to avoid getting programs that are just ending // Add one second to avoid getting programs that are just ending
@ -175,7 +223,7 @@
var nextDay = new Date(date.getTime() + msPerDay - 2000); var nextDay = new Date(date.getTime() + msPerDay - 2000);
console.log(nextDay); console.log(nextDay);
channelsPromise.then(function (channelsResult) { apiClient.getLiveTvChannels(channelQuery).then(function (channelsResult) {
var btnPreviousPage = context.querySelector('.btnPreviousPage'); var btnPreviousPage = context.querySelector('.btnPreviousPage');
var btnNextPage = context.querySelector('.btnNextPage'); var btnNextPage = context.querySelector('.btnNextPage');
@ -299,6 +347,37 @@
return null; return null;
} }
function getTimerIndicator(item) {
var status;
if (item.Type === 'SeriesTimer') {
return '<i class="md-icon programIcon seriesTimerIcon">&#xE062;</i>';
}
else if (item.TimerId || item.SeriesTimerId) {
status = item.Status || 'Cancelled';
}
else if (item.Type === 'Timer') {
status = item.Status;
}
else {
return '';
}
if (item.SeriesTimerId) {
if (status !== 'Cancelled') {
return '<i class="md-icon programIcon seriesTimerIcon">&#xE062;</i>';
}
return '<i class="md-icon programIcon seriesTimerIcon seriesTimerIcon-inactive">&#xE062;</i>';
}
return '<i class="md-icon programIcon timerIcon">&#xE061;</i>';
}
function getChannelProgramsHtml(context, date, channel, programs, options) { function getChannelProgramsHtml(context, date, channel, programs, options) {
var html = ''; var html = '';
@ -307,18 +386,28 @@
var endMs = startMs + msPerDay - 1; var endMs = startMs + msPerDay - 1;
programs = programs.filter(function (curr) { programs = programs.filter(function (curr) {
return curr.ChannelId == channel.Id; return curr.ChannelId === channel.Id;
}); });
var cssClass = layoutManager.tv ? 'channelPrograms channelPrograms-tv' : 'channelPrograms'; var outerCssClass = layoutManager.tv ? 'channelPrograms channelPrograms-tv' : 'channelPrograms';
html += '<div class="' + cssClass + '" data-channelid="' + channel.Id + '">'; html += '<div class="' + outerCssClass + '" data-channelid="' + channel.Id + '">';
var clickAction = layoutManager.tv ? 'link' : 'programdialog';
var categories = self.categoryOptions.categories || [];
var displayMovieContent = !categories.length || categories.indexOf('movies') !== -1;
var displaySportsContent = !categories.length || categories.indexOf('sports') !== -1;
var displayNewsContent = !categories.length || categories.indexOf('news') !== -1;
var displayKidsContent = !categories.length || categories.indexOf('kids') !== -1;
var displaySeriesContent = !categories.length || categories.indexOf('series') !== -1;
var enableColorCodedBackgrounds = userSettings.get('guide-colorcodedbackgrounds') === 'true';
for (var i = 0, length = programs.length; i < length; i++) { for (var i = 0, length = programs.length; i < length; i++) {
var program = programs[i]; var program = programs[i];
if (program.ChannelId != channel.Id) { if (program.ChannelId !== channel.Id) {
continue; continue;
} }
@ -344,20 +433,45 @@
endPercent *= 100; endPercent *= 100;
var cssClass = "programCell clearButton itemAction"; var cssClass = "programCell clearButton itemAction";
var addAccent = true; var accentCssClass = null;
var displayInnerContent = true;
if (program.IsKids) { if (program.IsKids) {
cssClass += " childProgramInfo"; cssClass += " childProgramInfo";
displayInnerContent = displayKidsContent;
accentCssClass = 'childAccent';
} else if (program.IsSports) { } else if (program.IsSports) {
cssClass += " sportsProgramInfo"; cssClass += " sportsProgramInfo";
displayInnerContent = displaySportsContent;
accentCssClass = 'sportsAccent';
} else if (program.IsNews) { } else if (program.IsNews) {
cssClass += " newsProgramInfo"; cssClass += " newsProgramInfo";
displayInnerContent = displayNewsContent;
accentCssClass = 'newsAccent';
} else if (program.IsMovie) { } else if (program.IsMovie) {
cssClass += " movieProgramInfo"; cssClass += " movieProgramInfo";
displayInnerContent = displayMovieContent;
accentCssClass = 'movieAccent';
}
else if (program.IsSeries) {
cssClass += " plainProgramInfo";
displayInnerContent = displaySeriesContent;
} }
else { else {
cssClass += " plainProgramInfo"; cssClass += " plainProgramInfo";
addAccent = false; displayInnerContent = displayMovieContent && displayNewsContent && displaySportsContent && displayKidsContent && displaySeriesContent;
}
if (!displayInnerContent) {
accentCssClass = null;
}
if (enableColorCodedBackgrounds && accentCssClass) {
cssClass += ' ' + accentCssClass;
accentCssClass = null;
} else {
accentCssClass = null;
} }
var timerAttributes = ''; var timerAttributes = '';
@ -367,49 +481,38 @@
if (program.SeriesTimerId) { if (program.SeriesTimerId) {
timerAttributes += ' data-seriestimerid="' + program.SeriesTimerId + '"'; timerAttributes += ' data-seriestimerid="' + program.SeriesTimerId + '"';
} }
html += '<button data-action="link"' + timerAttributes + ' data-isfolder="' + program.IsFolder + '" data-id="' + program.Id + '" data-serverid="' + program.ServerId + '" data-type="' + program.Type + '" class="' + cssClass + '" style="left:' + startPercent + '%;width:' + endPercent + '%;">';
var guideProgramNameClass = "guideProgramName"; html += '<button data-action="' + clickAction + '"' + timerAttributes + ' data-isfolder="' + program.IsFolder + '" data-id="' + program.Id + '" data-serverid="' + program.ServerId + '" data-type="' + program.Type + '" class="' + cssClass + '" style="left:' + startPercent + '%;width:' + endPercent + '%;">';
html += '<div class="' + guideProgramNameClass + '">'; if (displayInnerContent) {
var guideProgramNameClass = "guideProgramName";
if (program.IsLive && options.showLiveIndicator) { html += '<div class="' + guideProgramNameClass + '">';
html += '<span class="liveTvProgram guideProgramIndicator">' + globalize.translate('sharedcomponents#Live') + '</span>';
}
else if (program.IsPremiere && options.showPremiereIndicator) {
html += '<span class="premiereTvProgram guideProgramIndicator">' + globalize.translate('sharedcomponents#Premiere') + '</span>';
}
else if (program.IsSeries && !program.IsRepeat && options.showNewIndicator) {
html += '<span class="newTvProgram guideProgramIndicator">' + globalize.translate('sharedcomponents#AttributeNew') + '</span>';
}
else if (program.IsSeries && program.IsRepeat && options.showRepeatIndicator) {
html += '<span class="repeatTvProgram guideProgramIndicator">' + globalize.translate('sharedcomponents#Repeat') + '</span>';
}
html += program.Name; if (program.IsLive && options.showLiveIndicator) {
html += '</div>'; html += '<span class="liveTvProgram guideProgramIndicator">' + globalize.translate('sharedcomponents#Live') + '</span>';
}
else if (program.IsPremiere && options.showPremiereIndicator) {
html += '<span class="premiereTvProgram guideProgramIndicator">' + globalize.translate('sharedcomponents#Premiere') + '</span>';
}
else if (program.IsSeries && !program.IsRepeat && options.showNewIndicator) {
html += '<span class="newTvProgram guideProgramIndicator">' + globalize.translate('sharedcomponents#AttributeNew') + '</span>';
}
else if (program.IsSeries && program.IsRepeat && options.showRepeatIndicator) {
html += '<span class="repeatTvProgram guideProgramIndicator">' + globalize.translate('sharedcomponents#Repeat') + '</span>';
}
if (program.IsHD && options.showHdIcon) { html += program.Name;
html += '<i class="guideHdIcon md-icon programIcon">hd</i>'; html += '</div>';
}
if (program.SeriesTimerId) { if (program.IsHD && options.showHdIcon) {
html += '<i class="seriesTimerIcon md-icon programIcon">fiber_smart_record</i>'; html += '<i class="guideHdIcon md-icon programIcon">hd</i>';
} }
else if (program.TimerId) {
html += '<i class="timerIcon md-icon programIcon">fiber_manual_record</i>';
}
if (addAccent) { html += getTimerIndicator(program);
if (program.IsKids) { if (accentCssClass) {
html += '<div class="programAccent childAccent"></div>'; html += '<div class="programAccent ' + accentCssClass + '"></div>';
} else if (program.IsSports) {
html += '<div class="programAccent sportsAccent"></div>';
} else if (program.IsNews) {
html += '<div class="programAccent newsAccent"></div>';
} else if (program.IsMovie) {
html += '<div class="programAccent movieAccent"></div>';
} }
} }
@ -431,11 +534,11 @@
var allowIndicators = dom.getWindowSize().innerWidth >= 600; var allowIndicators = dom.getWindowSize().innerWidth >= 600;
var options = { var options = {
showHdIcon: allowIndicators && userSettings.get('guide-indicator-hd') == 'true', showHdIcon: allowIndicators && userSettings.get('guide-indicator-hd') === 'true',
showLiveIndicator: allowIndicators && userSettings.get('guide-indicator-live') != 'false', showLiveIndicator: allowIndicators && userSettings.get('guide-indicator-live') !== 'false',
showPremiereIndicator: allowIndicators && userSettings.get('guide-indicator-premiere') != 'false', showPremiereIndicator: allowIndicators && userSettings.get('guide-indicator-premiere') !== 'false',
showNewIndicator: allowIndicators && userSettings.get('guide-indicator-new') == 'true', showNewIndicator: allowIndicators && userSettings.get('guide-indicator-new') === 'true',
showRepeatIndicator: allowIndicators && userSettings.get('guide-indicator-repeat') == 'true' showRepeatIndicator: allowIndicators && userSettings.get('guide-indicator-repeat') === 'true'
}; };
for (var i = 0, length = channels.length; i < length; i++) { for (var i = 0, length = channels.length; i < length; i++) {
@ -497,19 +600,6 @@
imageLoader.lazyChildren(channelList); imageLoader.lazyChildren(channelList);
} }
function parentWithClass(elem, className) {
while (!elem.classList || !elem.classList.contains(className)) {
elem = elem.parentNode;
if (!elem) {
return null;
}
}
return elem;
}
function renderGuide(context, date, channels, programs, apiClient) { function renderGuide(context, date, channels, programs, apiClient) {
//var list = []; //var list = [];
@ -555,7 +645,7 @@
var channelRowId = null; var channelRowId = null;
if (activeElement) { if (activeElement) {
channelRowId = parentWithClass(activeElement, 'channelPrograms'); channelRowId = dom.parentWithClass(activeElement, 'channelPrograms');
channelRowId = channelRowId && channelRowId.getAttribute ? channelRowId.getAttribute('data-channelid') : null; channelRowId = channelRowId && channelRowId.getAttribute ? channelRowId.getAttribute('data-channelid') : null;
} }
@ -572,7 +662,7 @@
var focusElem; var focusElem;
if (itemId) { if (itemId) {
focusElem = context.querySelector('[data-id="' + itemId + '"]') focusElem = context.querySelector('[data-id="' + itemId + '"]');
} }
if (focusElem) { if (focusElem) {
@ -582,7 +672,7 @@
var autoFocusParent; var autoFocusParent;
if (channelRowId) { if (channelRowId) {
autoFocusParent = context.querySelector('[data-channelid="' + channelRowId + '"]') autoFocusParent = context.querySelector('[data-channelid="' + channelRowId + '"]');
} }
if (!autoFocusParent) { if (!autoFocusParent) {
@ -637,13 +727,8 @@
reloadGuide(page, newStartDate); reloadGuide(page, newStartDate);
var dateText = datetime.getLocaleDateStringParts(date); var dateText = datetime.toLocaleDateString(date, { weekday: 'short', month: 'short', day: 'numeric' });
if (dateText.length == 1) {
dateText = dateText[0];
} else {
dateText = '<div>' + dateText[0] + '</div><div class="guideDateTextDate">' + dateText[1] + '</div>';
}
page.querySelector('.guideDateText').innerHTML = dateText; page.querySelector('.guideDateText').innerHTML = dateText;
} }
@ -671,7 +756,7 @@
while (start <= end) { while (start <= end) {
dateOptions.push({ dateOptions.push({
name: datetime.getLocaleDateStringParts(start).join(' '), name: datetime.toLocaleDateString(start, { weekday: 'long', month: 'long', day: 'numeric' }),
id: start.getTime() id: start.getTime()
}); });
@ -704,7 +789,7 @@
var selectedDate = currentDate || new Date(); var selectedDate = currentDate || new Date();
dateOptions.forEach(function (d) { dateOptions.forEach(function (d) {
d.selected = new Date(d.id).getDate() == selectedDate.getDate(); d.selected = new Date(d.id).getDate() === selectedDate.getDate();
}); });
require(['actionsheet'], function (actionsheet) { require(['actionsheet'], function (actionsheet) {
@ -735,22 +820,9 @@
} }
} }
function parentWithClass(elem, className) {
while (!elem.classList || !elem.classList.contains(className)) {
elem = elem.parentNode;
if (!elem) {
return null;
}
}
return elem;
}
function onProgramGridFocus(e) { function onProgramGridFocus(e) {
var programCell = parentWithClass(e.target, 'programCell'); var programCell = dom.parentWithClass(e.target, 'programCell');
if (!programCell) { if (!programCell) {
return; return;
@ -781,7 +853,7 @@
var icon = cell.querySelector('.timerIcon'); var icon = cell.querySelector('.timerIcon');
if (!icon) { if (!icon) {
cell.insertAdjacentHTML('beforeend', '<i class="timerIcon md-icon">fiber_manual_record</i>'); cell.insertAdjacentHTML('beforeend', '<i class="timerIcon md-icon">&#xE061;</i>');
} }
if (newTimerId) { if (newTimerId) {
@ -855,19 +927,16 @@
context.querySelector('.btnUnlockGuide').addEventListener('click', function () { context.querySelector('.btnUnlockGuide').addEventListener('click', function () {
currentStartIndex = 0; currentStartIndex = 0;
channelsPromise = null;
reloadPage(context); reloadPage(context);
}); });
context.querySelector('.btnNextPage').addEventListener('click', function () { context.querySelector('.btnNextPage').addEventListener('click', function () {
currentStartIndex += currentChannelLimit; currentStartIndex += currentChannelLimit;
channelsPromise = null;
reloadPage(context); reloadPage(context);
}); });
context.querySelector('.btnPreviousPage').addEventListener('click', function () { context.querySelector('.btnPreviousPage').addEventListener('click', function () {
currentStartIndex = Math.max(currentStartIndex - currentChannelLimit, 0); currentStartIndex = Math.max(currentStartIndex - currentChannelLimit, 0);
channelsPromise = null;
reloadPage(context); reloadPage(context);
}); });
@ -875,6 +944,10 @@
showViewSettings(self); showViewSettings(self);
}); });
context.querySelector('.btnCategories').addEventListener('click', function () {
showCategoryOptions(self);
});
context.classList.add('tvguide'); context.classList.add('tvguide');
setScrollEvents(context, true); setScrollEvents(context, true);
@ -889,7 +962,7 @@
self.refresh(); self.refresh();
}); });
}; }
return Guide; return Guide;
}); });

View file

@ -0,0 +1,15 @@
.newTvProgram {
background: #64A239;
}
.liveTvProgram {
background: #EC407A;
}
.premiereTvProgram {
background: #EF6C00;
}
.repeatTvProgram {
background: #009688;
}

View file

@ -1,6 +1,6 @@
<div class="tvGuideHeader"> <div class="tvGuideHeader">
<div class="channelTimeslotHeader"> <div class="channelTimeslotHeader">
<button is="emby-button" type="button" class="btnSelectDate block"> <button is="emby-button" type="button" class="btnSelectDate block button-flat">
<div class="btnSelectDateContent"> <div class="btnSelectDateContent">
<div class="guideDateText"> <div class="guideDateText">
</div> </div>
@ -14,10 +14,19 @@
<div class="timeslotHeaders smoothScrollX guideScroller" style="scroll-behavior: auto;"></div> <div class="timeslotHeaders smoothScrollX guideScroller" style="scroll-behavior: auto;"></div>
</div> </div>
<div class="smoothScrollY guideVerticalScroller programContainer guideScroller" style="flex-grow: 1;"> <div style="display: flex;flex-grow:1;overflow:hidden;">
<div class="channelList"></div>
<div class="programGridContainer programGrid smoothScrollX guideScroller" style="white-space: nowrap;"> <button is="emby-button" type="button" class="btnCategories">
<div class="btnCategoriesText">${Categories}</div>
</button>
<div class="smoothScrollY guideVerticalScroller programContainer guideScroller" style="flex-grow: 1;">
<div class="channelsContainer">
<div class="channelList"></div>
</div>
<div class="programGridContainer programGrid smoothScrollX guideScroller" style="white-space: nowrap;">
</div>
</div> </div>
</div> </div>

View file

@ -1,4 +1,5 @@
define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager', 'focusManager', 'globalize', 'scrollHelper', 'imageLoader', 'require', 'cardStyle', 'formDialogStyle', 'emby-button', 'paper-icon-button-light'], function (dialogHelper, connectionManager, loading, dom, layoutManager, focusManager, globalize, scrollHelper, imageLoader, require) { define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager', 'focusManager', 'globalize', 'scrollHelper', 'imageLoader', 'require', 'cardStyle', 'formDialogStyle', 'emby-button', 'paper-icon-button-light'], function (dialogHelper, connectionManager, loading, dom, layoutManager, focusManager, globalize, scrollHelper, imageLoader, require) {
'use strict';
var currentItem; var currentItem;
var hasChanges = false; var hasChanges = false;
@ -78,11 +79,11 @@
options.type = type; options.type = type;
options.index = index; options.index = index;
if (type == 'Backdrop') { if (type === 'Backdrop') {
options.tag = item.BackdropImageTags[index]; options.tag = item.BackdropImageTags[index];
} else if (type == 'Screenshot') { } else if (type === 'Screenshot') {
options.tag = item.ScreenshotImageTags[index]; options.tag = item.ScreenshotImageTags[index];
} else if (type == 'Primary') { } else if (type === 'Primary') {
options.tag = item.PrimaryImageTag || item.ImageTags[type]; options.tag = item.PrimaryImageTag || item.ImageTags[type];
} else { } else {
options.tag = item.ImageTags[type]; options.tag = item.ImageTags[type];
@ -101,7 +102,7 @@
cssClass += " backdropCard backdropCard-scalable"; cssClass += " backdropCard backdropCard-scalable";
if (tagName == 'button') { if (tagName === 'button') {
cssClass += ' card-focusscale btnImageCard'; cssClass += ' card-focusscale btnImageCard';
cardBoxCssClass += ' cardBox-focustransform cardBox-focustransform-transition'; cardBoxCssClass += ' cardBox-focustransform cardBox-focustransform-transition';
@ -142,27 +143,27 @@
if (enableFooterButtons) { if (enableFooterButtons) {
html += '<div class="cardText cardTextCentered">'; html += '<div class="cardText cardTextCentered">';
if (image.ImageType == "Backdrop" || image.ImageType == "Screenshot") { if (image.ImageType === "Backdrop" || image.ImageType === "Screenshot") {
if (index > 0) { if (index > 0) {
html += '<button is="paper-icon-button-light" class="btnMoveImage autoSize" data-imagetype="' + image.ImageType + '" data-index="' + image.ImageIndex + '" data-newindex="' + (image.ImageIndex - 1) + '" title="' + globalize.translate('sharedcomponents#MoveLeft') + '"><i class="md-icon">chevron_left</i></button>'; html += '<button type="button" is="paper-icon-button-light" class="btnMoveImage autoSize" data-imagetype="' + image.ImageType + '" data-index="' + image.ImageIndex + '" data-newindex="' + (image.ImageIndex - 1) + '" title="' + globalize.translate('sharedcomponents#MoveLeft') + '"><i class="md-icon">chevron_left</i></button>';
} else { } else {
html += '<button is="paper-icon-button-light" class="autoSize" disabled title="' + globalize.translate('sharedcomponents#MoveLeft') + '"><i class="md-icon">chevron_left</i></button>'; html += '<button type="button" is="paper-icon-button-light" class="autoSize" disabled title="' + globalize.translate('sharedcomponents#MoveLeft') + '"><i class="md-icon">chevron_left</i></button>';
} }
if (index < numImages - 1) { if (index < numImages - 1) {
html += '<button is="paper-icon-button-light" class="btnMoveImage autoSize" data-imagetype="' + image.ImageType + '" data-index="' + image.ImageIndex + '" data-newindex="' + (image.ImageIndex + 1) + '" title="' + globalize.translate('sharedcomponents#MoveRight') + '"><i class="md-icon">chevron_right</i></button>'; html += '<button type="button" is="paper-icon-button-light" class="btnMoveImage autoSize" data-imagetype="' + image.ImageType + '" data-index="' + image.ImageIndex + '" data-newindex="' + (image.ImageIndex + 1) + '" title="' + globalize.translate('sharedcomponents#MoveRight') + '"><i class="md-icon">chevron_right</i></button>';
} else { } else {
html += '<button is="paper-icon-button-light" class="autoSize" disabled title="' + globalize.translate('sharedcomponents#MoveRight') + '"><i class="md-icon">chevron_right</i></button>'; html += '<button type="button" is="paper-icon-button-light" class="autoSize" disabled title="' + globalize.translate('sharedcomponents#MoveRight') + '"><i class="md-icon">chevron_right</i></button>';
} }
} }
else { else {
if (imageProviders.length) { if (imageProviders.length) {
html += '<button is="paper-icon-button-light" data-imagetype="' + image.ImageType + '" class="btnSearchImages autoSize" title="' + globalize.translate('sharedcomponents#Search') + '"><i class="md-icon">search</i></button>'; html += '<button type="button" is="paper-icon-button-light" data-imagetype="' + image.ImageType + '" class="btnSearchImages autoSize" title="' + globalize.translate('sharedcomponents#Search') + '"><i class="md-icon">search</i></button>';
} }
} }
html += '<button is="paper-icon-button-light" data-imagetype="' + image.ImageType + '" data-index="' + (image.ImageIndex != null ? image.ImageIndex : "null") + '" class="btnDeleteImage autoSize" title="' + globalize.translate('sharedcomponents#Delete') + '"><i class="md-icon">delete</i></button>'; html += '<button type="button" is="paper-icon-button-light" data-imagetype="' + image.ImageType + '" data-index="' + (image.ImageIndex != null ? image.ImageIndex : "null") + '" class="btnDeleteImage autoSize" title="' + globalize.translate('sharedcomponents#Delete') + '"><i class="md-icon">delete</i></button>';
html += '</div>'; html += '</div>';
} }
@ -192,7 +193,13 @@
require(['confirm'], function (confirm) { require(['confirm'], function (confirm) {
confirm(globalize.translate('sharedcomponents#ConfirmDeleteImage')).then(afterConfirm); confirm({
text: globalize.translate('sharedcomponents#ConfirmDeleteImage'),
confirmText: globalize.translate('sharedcomponents#Delete'),
primary: 'cancel'
}).then(afterConfirm);
}); });
} }
@ -202,6 +209,11 @@
hasChanges = true; hasChanges = true;
reload(context, null, focusContext); reload(context, null, focusContext);
}, function() {
require(['alert'], function (alert) {
alert(globalize.translate('sharedcomponents#DefaultErrorMessage'));
});
}); });
} }
@ -227,31 +239,12 @@
elem.innerHTML = html; elem.innerHTML = html;
imageLoader.lazyChildren(elem); imageLoader.lazyChildren(elem);
addListeners(elem, 'btnSearchImages', 'click', function () {
showImageDownloader(page, this.getAttribute('data-imagetype'));
});
addListeners(elem, 'btnDeleteImage', 'click', function () {
var type = this.getAttribute('data-imagetype');
var index = this.getAttribute('data-index');
index = index == "null" ? null : parseInt(index);
deleteImage(page, currentItem.Id, type, index, apiClient, true);
});
addListeners(elem, 'btnMoveImage', 'click', function () {
var type = this.getAttribute('data-imagetype');
var index = this.getAttribute('data-index');
var newIndex = this.getAttribute('data-newindex');
moveImage(page, apiClient, currentItem.Id, type, index, newIndex, dom.parentWithClass(this, 'itemsContainer'));
});
} }
function renderStandardImages(page, apiClient, item, imageInfos, imageProviders) { function renderStandardImages(page, apiClient, item, imageInfos, imageProviders) {
var images = imageInfos.filter(function (i) { var images = imageInfos.filter(function (i) {
return i.ImageType != "Screenshot" && i.ImageType != "Backdrop" && i.ImageType != "Chapter"; return i.ImageType !== "Screenshot" && i.ImageType !== "Backdrop" && i.ImageType !== "Chapter";
}); });
renderImages(page, item, apiClient, images, imageProviders, page.querySelector('#images')); renderImages(page, item, apiClient, images, imageProviders, page.querySelector('#images'));
@ -260,7 +253,7 @@
function renderBackdrops(page, apiClient, item, imageInfos, imageProviders) { function renderBackdrops(page, apiClient, item, imageInfos, imageProviders) {
var images = imageInfos.filter(function (i) { var images = imageInfos.filter(function (i) {
return i.ImageType == "Backdrop"; return i.ImageType === "Backdrop";
}).sort(function (a, b) { }).sort(function (a, b) {
return a.ImageIndex - b.ImageIndex; return a.ImageIndex - b.ImageIndex;
@ -277,7 +270,7 @@
function renderScreenshots(page, apiClient, item, imageInfos, imageProviders) { function renderScreenshots(page, apiClient, item, imageInfos, imageProviders) {
var images = imageInfos.filter(function (i) { var images = imageInfos.filter(function (i) {
return i.ImageType == "Screenshot"; return i.ImageType === "Screenshot";
}).sort(function (a, b) { }).sort(function (a, b) {
return a.ImageIndex - b.ImageIndex; return a.ImageIndex - b.ImageIndex;
@ -299,6 +292,10 @@
hasChanges = true; hasChanges = true;
reload(page); reload(page);
}); });
}, function () {
require(['alert'], function (alert) {
alert('This feature is coming soon to Emby Theater.');
});
}); });
} }
@ -322,7 +319,7 @@
id: 'delete' id: 'delete'
}); });
if (type == 'Backdrop' || type == 'Screenshot') { if (type === 'Backdrop' || type === 'Screenshot') {
if (index > 0) { if (index > 0) {
commands.push({ commands.push({
name: globalize.translate('sharedcomponents#MoveLeft'), name: globalize.translate('sharedcomponents#MoveLeft'),
@ -374,9 +371,9 @@
}); });
} }
function initEditor(page, options) { function initEditor(context, options) {
addListeners(page, 'btnOpenUploadMenu', 'click', function () { addListeners(context, 'btnOpenUploadMenu', 'click', function () {
var imageType = this.getAttribute('data-imagetype'); var imageType = this.getAttribute('data-imagetype');
require(['components/imageuploader/imageuploader'], function (imageUploader) { require(['components/imageuploader/imageuploader'], function (imageUploader) {
@ -390,18 +387,42 @@
if (hasChanged) { if (hasChanged) {
hasChanges = true; hasChanges = true;
reload(page); reload(context);
} }
}); });
}, function () {
require(['alert'], function (alert) {
alert('This feature is coming soon to Emby Theater.');
});
}); });
}); });
addListeners(page, 'btnBrowseAllImages', 'click', function () { addListeners(context, 'btnSearchImages', 'click', function () {
showImageDownloader(page, this.getAttribute('data-imagetype') || 'Primary'); showImageDownloader(context, this.getAttribute('data-imagetype'));
}); });
addListeners(page, 'btnImageCard', 'click', function () { addListeners(context, 'btnBrowseAllImages', 'click', function () {
showActionSheet(page, this); showImageDownloader(context, this.getAttribute('data-imagetype') || 'Primary');
});
addListeners(context, 'btnImageCard', 'click', function () {
showActionSheet(context, this);
});
addListeners(context, 'btnDeleteImage', 'click', function () {
var type = this.getAttribute('data-imagetype');
var index = this.getAttribute('data-index');
index = index === "null" ? null : parseInt(index);
var apiClient = connectionManager.getApiClient(currentItem.ServerId);
deleteImage(context, currentItem.Id, type, index, apiClient, true);
});
addListeners(context, 'btnMoveImage', 'click', function () {
var type = this.getAttribute('data-imagetype');
var index = this.getAttribute('data-index');
var newIndex = this.getAttribute('data-newindex');
var apiClient = connectionManager.getApiClient(currentItem.ServerId);
moveImage(context, apiClient, currentItem.Id, type, index, newIndex, dom.parentWithClass(this, 'itemsContainer'));
}); });
} }

View file

@ -1,16 +1,25 @@
define([], function () { define(['dom'], function (dom) {
'use strict';
function loadImage(elem, url) { function loadImage(elem, url) {
if (elem.tagName !== "IMG") { if (elem.tagName !== "IMG") {
elem.style.backgroundImage = "url('" + url + "')"; elem.style.backgroundImage = "url('" + url + "')";
return Promise.resolve(elem); return Promise.resolve();
} else {
elem.setAttribute("src", url);
return Promise.resolve(elem);
} }
return loadImageIntoImg(elem, url);
}
function loadImageIntoImg(elem, url) {
return new Promise(function (resolve, reject) {
dom.addEventListener(elem, 'load', resolve, {
once: true
});
elem.setAttribute("src", url);
});
} }
return { return {

View file

@ -1,18 +1,19 @@
define(['visibleinviewport', 'imageFetcher', 'layoutManager', 'events', 'browser', 'dom'], function (visibleinviewport, imageFetcher, layoutManager, events, browser, dom) { define(['visibleinviewport', 'imageFetcher', 'layoutManager', 'events', 'browser', 'dom', 'appSettings', 'require'], function (visibleinviewport, imageFetcher, layoutManager, events, browser, dom, appSettings, require) {
'use strict';
var thresholdX; var thresholdX;
var thresholdY; var thresholdY;
var requestIdleCallback = window.requestIdleCallback || function (fn) {
fn();
};
//var imagesWorker = new Worker(require.toUrl('.').split('?')[0] + '/imagesworker.js');
var supportsIntersectionObserver = function () { var supportsIntersectionObserver = function () {
if (window.IntersectionObserver) { if (window.IntersectionObserver) {
// The api exists in chrome 50 but doesn't work
if (browser.chrome) {
var version = parseInt(browser.version.split('.')[0]);
return version >= 51;
}
return true; return true;
} }
@ -25,8 +26,8 @@ define(['visibleinviewport', 'imageFetcher', 'layoutManager', 'events', 'browser
var y = screen.availHeight; var y = screen.availHeight;
if (browser.touch) { if (browser.touch) {
x *= 2; x *= 1.5;
y *= 2; y *= 1.5;
} }
thresholdX = x; thresholdX = x;
@ -53,14 +54,174 @@ define(['visibleinviewport', 'imageFetcher', 'layoutManager', 'events', 'browser
if (!source) { if (!source) {
source = elem.getAttribute('data-src'); source = elem.getAttribute('data-src');
} }
if (source) {
if (enableFade && !layoutManager.tv && enableEffects !== false) { if (!source) {
imageFetcher.loadImage(elem, source).then(fadeIn); return;
} else {
imageFetcher.loadImage(elem, source);
}
elem.removeAttribute("data-src");
} }
fillImageElement(elem, source, enableEffects);
}
function fillImageElement(elem, source, enableEffects) {
imageFetcher.loadImage(elem, source).then(function () {
var fillingVibrant = elem.tagName !== 'IMG' ? false : fillVibrant(elem, source);
if (enableFade && !layoutManager.tv && enableEffects !== false && !fillingVibrant) {
fadeIn(elem);
}
elem.removeAttribute("data-src");
});
}
//var placeholder = document.createElement('div');
//imagesWorker.onmessage = function (evt) {
// placeholder.dispatchEvent(new CustomEvent('decoded', {
// detail: evt.data,
// bubbles: false,
// cancellable: false
// }));
//};
//var uniqueId = 0;
//function fillCanvas(elem, source) {
// var newUniqueId = (++uniqueId);
// imagesWorker.postMessage({
// url: source,
// id: newUniqueId
// });
// placeholder.addEventListener('decoded', function (e) {
// if (e.detail.id == newUniqueId) {
// var imageBitmap = e.detail.imageBitmap;
// var canvas = document.createElement('canvas');
// var canvasContext = canvas.getContext('2d');
// //drawWidth *= ratio;
// //drawHeight *= ratio;
// // https://stackoverflow.com/questions/21961839/simulation-background-size-cover-in-canvas/21961894#21961894
// canvasContext.imageSmoothingEnabled = false;
// var width = canvas.width = elem.offsetWidth;
// var height = canvas.height = elem.offsetHeight;
// canvasContext.drawImage(imageBitmap, 0, 0, imageBitmap.width, imageBitmap.height, 0, 0, width, height);
// fillVibrant(elem, source, canvas, canvasContext);
// elem.insertBefore(canvas, elem.firstChild);
// elem.removeAttribute("data-src");
// }
// });
//}
function fillVibrant(img, url, canvas, canvasContext) {
var vibrantElement = img.getAttribute('data-vibrant');
if (!vibrantElement) {
return false;
}
if (window.Vibrant) {
fillVibrantOnLoaded(img, url, vibrantElement, canvas, canvasContext);
return true;
}
require(['vibrant'], function () {
fillVibrantOnLoaded(img, url, vibrantElement, canvas, canvasContext);
});
return true;
}
function fillVibrantOnLoaded(img, url, vibrantElement, canvas, canvasContext) {
vibrantElement = document.getElementById(vibrantElement);
if (!vibrantElement) {
return;
}
requestIdleCallback(function () {
//var now = new Date().getTime();
var swatch = getVibrantInfo(canvas || img, url, canvasContext).split('|');
//console.log('vibrant took ' + (new Date().getTime() - now) + 'ms');
if (swatch.length) {
var index = 0;
vibrantElement.style.backgroundColor = swatch[index];
vibrantElement.style.color = swatch[index + 1];
}
});
/*
* Results into:
* Vibrant #7a4426
* Muted #7b9eae
* DarkVibrant #348945
* DarkMuted #141414
* LightVibrant #f3ccb4
*/
}
function getSettingsKey(url) {
var parts = url.split('://');
url = parts[parts.length - 1];
url = url.substring(url.indexOf('/') + 1);
url = url.split('?')[0];
var cacheKey = 'vibrant11';
return cacheKey + url;
}
function getCachedVibrantInfo(url) {
return appSettings.get(getSettingsKey(url));
}
function getVibrantInfo(img, url, canvasContext) {
var value = getCachedVibrantInfo(url);
if (value) {
return value;
}
var vibrant = new Vibrant(img, canvasContext);
var swatches = vibrant.swatches();
value = '';
var swatch = swatches.DarkVibrant;
if (swatch) {
value += swatch.getHex() + '|' + swatch.getBodyTextColor();
}
//swatch = swatches.DarkMuted;
//if (swatch) {
// value += '|' + swatch.getHex() + '|' + swatch.getBodyTextColor();
//} else {
// value += '||';
//}
//swatch = swatches.Vibrant;
//if (swatch) {
// value += '|' + swatch.getHex() + '|' + swatch.getBodyTextColor();
//} else {
// value += '||';
//}
//swatch = swatches.Muted;
//if (swatch) {
// value += '|' + swatch.getHex() + '|' + swatch.getBodyTextColor();
//} else {
// value += '||';
//}
appSettings.set(getSettingsKey(url), value);
return value;
} }
function fadeIn(elem) { function fadeIn(elem) {
@ -231,31 +392,33 @@ define(['visibleinviewport', 'imageFetcher', 'layoutManager', 'events', 'browser
var result; var result;
if (values.length % 2) if (values.length % 2) {
result = values[half]; result = values[half];
else }
else {
result = (values[half - 1] + values[half]) / 2.0; result = (values[half - 1] + values[half]) / 2.0;
}
// If really close to 2:3 (poster image), just return 2:3 // If really close to 2:3 (poster image), just return 2:3
var aspect2x3 = 2 / 3; var aspect2x3 = 2 / 3;
if (Math.abs(aspect2x3 - result) <= .15) { if (Math.abs(aspect2x3 - result) <= 0.15) {
return aspect2x3; return aspect2x3;
} }
// If really close to 16:9 (episode image), just return 16:9 // If really close to 16:9 (episode image), just return 16:9
var aspect16x9 = 16 / 9; var aspect16x9 = 16 / 9;
if (Math.abs(aspect16x9 - result) <= .2) { if (Math.abs(aspect16x9 - result) <= 0.2) {
return aspect16x9; return aspect16x9;
} }
// If really close to 1 (square image), just return 1 // If really close to 1 (square image), just return 1
if (Math.abs(1 - result) <= .15) { if (Math.abs(1 - result) <= 0.15) {
return 1; return 1;
} }
// If really close to 4:3 (poster image), just return 2:3 // If really close to 4:3 (poster image), just return 2:3
var aspect4x3 = 4 / 3; var aspect4x3 = 4 / 3;
if (Math.abs(aspect4x3 - result) <= .15) { if (Math.abs(aspect4x3 - result) <= 0.15) {
return aspect4x3; return aspect4x3;
} }
@ -274,6 +437,7 @@ define(['visibleinviewport', 'imageFetcher', 'layoutManager', 'events', 'browser
self.lazyImage = fillImage; self.lazyImage = fillImage;
self.lazyChildren = lazyChildren; self.lazyChildren = lazyChildren;
self.getPrimaryImageAspectRatio = getPrimaryImageAspectRatio; self.getPrimaryImageAspectRatio = getPrimaryImageAspectRatio;
self.getCachedVibrantInfo = getCachedVibrantInfo;
return self; return self;
}); });

View file

@ -0,0 +1,177 @@
define(['cryptojs-md5'], function () {
'use strict';
var indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.OIndexedDB || window.msIndexedDB;
var dbVersion = 1;
var imagesTableName = "images";
var db;
function createObjectStore(dataBase) {
dataBase.createObjectStore(imagesTableName, { keyPath: "id" });
db = dataBase;
}
// Create/open database
var request = indexedDB.open("imagesDb2", dbVersion);
request.onupgradeneeded = function () {
createObjectStore(request.result);
};
request.onsuccess = function (event) {
console.log("Success creating/accessing IndexedDB database");
var localDb = request.result;
localDb.onerror = function (event) {
console.log("Error creating/accessing IndexedDB database");
};
// Interim solution for Google Chrome to create an objectStore. Will be deprecated
if (localDb.setVersion) {
if (localDb.version !== dbVersion) {
var setVersion = localDb.setVersion(dbVersion);
setVersion.onsuccess = function () {
createObjectStore(localDb);
};
} else {
db = localDb;
}
} else {
db = localDb;
}
};
function revoke(url) {
//URL.revokeObjectURL(url);
}
function loadImage(elem, url) {
if (elem.tagName !== "IMG") {
elem.style.backgroundImage = "url('" + url + "')";
revoke(url);
return Promise.resolve(elem);
} else {
elem.setAttribute("src", url);
revoke(url);
return Promise.resolve(elem);
}
}
function getCacheKey(url) {
// Try to strip off the domain to share the cache between local and remote connections
var index = url.indexOf('://');
if (index !== -1) {
url = url.substring(index + 3);
index = url.indexOf('/');
if (index !== -1) {
url = url.substring(index + 1);
}
}
return CryptoJS.MD5(url).toString();
}
function getFromDb(key) {
return new Promise(function (resolve, reject) {
var transaction = db.transaction(imagesTableName, "read");
// Retrieve the file that was just stored
var request = transaction.objectStore(imagesTableName).get(key);
request.onsuccess = function (event) {
var imgFile = event.target.result;
// Get window.URL object
var URL = window.URL || window.webkitURL;
// Create and revoke ObjectURL
var imgURL = URL.createObjectURL(imgFile);
resolve(imgURL);
};
request.onerror = reject;
});
}
function saveImageToDb(blob, key, resolve) {
// Open a transaction to the database
var transaction = db.transaction(imagesTableName, "readwrite");
// Put the blob into the dabase
var put = transaction.objectStore(imagesTableName).put({ id: key, data: blob });
// Get window.URL object
var URL = window.URL || window.webkitURL;
var imgURL = URL.createObjectURL(blob);
resolve(imgURL);
}
function getImageUrl(originalUrl) {
var key = getCacheKey(originalUrl);
return getFromDb(key).catch(function () {
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open("GET", originalUrl, true);
// Set the responseType to blob
xhr.responseType = "blob";
xhr.addEventListener("load", function () {
if (xhr.status === 200) {
// Put the received blob into IndexedDB
saveImageToDb(xhr.response, key, resolve);
} else {
reject();
}
}, false);
xhr.onerror = reject;
// Send XHR
xhr.send();
});
});
}
return {
loadImage: function (elem, url) {
if (!db) {
return loadImage(elem, url);
}
return getImageUrl(url).then(function (localUrl) {
return loadImage(elem, localUrl);
}, function () {
return loadImage(elem, url);
});
}
};
});

View file

@ -1,4 +1,5 @@
define(['cryptojs-md5'], function () { define(['cryptojs-md5'], function () {
'use strict';
function loadImage(elem, url) { function loadImage(elem, url) {
@ -20,7 +21,7 @@ define(['cryptojs-md5'], function () {
function createDir(rootDirEntry, folders, callback, errorCallback) { function createDir(rootDirEntry, folders, callback, errorCallback) {
// Throw out './' or '/' and move on to prevent something like '/foo/.//bar'. // Throw out './' or '/' and move on to prevent something like '/foo/.//bar'.
if (folders[0] == '.' || folders[0] == '') { if (folders[0] === '.' || folders[0] === '') {
folders = folders.slice(1); folders = folders.slice(1);
} }
rootDirEntry.getDirectory(folders[0], { create: true }, function (dirEntry) { rootDirEntry.getDirectory(folders[0], { create: true }, function (dirEntry) {
@ -140,12 +141,12 @@ define(['cryptojs-md5'], function () {
// Try to strip off the domain to share the cache between local and remote connections // Try to strip off the domain to share the cache between local and remote connections
var index = url.indexOf('://'); var index = url.indexOf('://');
if (index != -1) { if (index !== -1) {
url = url.substring(index + 3); url = url.substring(index + 3);
index = url.indexOf('/'); index = url.indexOf('/');
if (index != -1) { if (index !== -1) {
url = url.substring(index + 1); url = url.substring(index + 1);
} }
@ -163,12 +164,12 @@ define(['cryptojs-md5'], function () {
xhr.responseType = "arraybuffer"; xhr.responseType = "arraybuffer";
xhr.onload = function (e) { xhr.onload = function (e) {
if (this.status == 200) { if (this.status === 200) {
writeData(dir, filename, this.getResponseHeader('Content-Type'), this.response, callback, errorCallback); writeData(dir, filename, this.getResponseHeader('Content-Type'), this.response, callback, errorCallback);
} else { } else {
errorCallback(); errorCallback();
} }
} };
xhr.send(); xhr.send();
} }
@ -200,7 +201,7 @@ define(['cryptojs-md5'], function () {
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
if (originalUrl.indexOf('tag=') != -1) { if (originalUrl.indexOf('tag=') !== -1) {
originalUrl += "&accept=webp"; originalUrl += "&accept=webp";
} }

View file

@ -28,6 +28,10 @@
color: #CB272A; color: #CB272A;
} }
.timerIndicator-inactive {
color: #888;
}
.indicator + .indicator { .indicator + .indicator {
margin-left: .25em; margin-left: .25em;
} }
@ -73,4 +77,4 @@
.fullSyncIndicator { .fullSyncIndicator {
background: rgba(82,181,75,1); background: rgba(82,181,75,1);
} }

View file

@ -1,9 +1,10 @@
define(['css!./indicators.css', 'material-icons'], function () { define(['css!./indicators.css', 'material-icons'], function () {
'use strict';
function enableProgressIndicator(item) { function enableProgressIndicator(item) {
if (item.MediaType == 'Video') { if (item.MediaType === 'Video') {
if (item.Type != 'TvChannel') { if (item.Type !== 'TvChannel') {
return true; return true;
} }
} }
@ -27,7 +28,7 @@ define(['css!./indicators.css', 'material-icons'], function () {
function getProgressBarHtml(item, options) { function getProgressBarHtml(item, options) {
if (enableProgressIndicator(item)) { if (enableProgressIndicator(item)) {
if (item.Type == "Recording" && item.CompletionPercentage) { if (item.Type === "Recording" && item.CompletionPercentage) {
return getProgressHtml(item.CompletionPercentage, options); return getProgressHtml(item.CompletionPercentage, options);
} }
@ -48,9 +49,9 @@ define(['css!./indicators.css', 'material-icons'], function () {
function enablePlayedIndicator(item) { function enablePlayedIndicator(item) {
if (item.Type == "Series" || item.Type == "Season" || item.Type == "BoxSet" || item.MediaType == "Video" || item.MediaType == "Game" || item.MediaType == "Book") { if (item.Type === "Series" || item.Type === "Season" || item.Type === "BoxSet" || item.MediaType === "Video" || item.MediaType === "Game" || item.MediaType === "Book") {
if (item.Type != 'TvChannel') { if (item.Type !== 'TvChannel') {
return true; return true;
} }
} }
@ -98,19 +99,38 @@ define(['css!./indicators.css', 'material-icons'], function () {
function getTimerIndicator(item) { function getTimerIndicator(item) {
if (item.SeriesTimerId) { var status;
return '<i class="md-icon timerIndicator indicatorIcon">fiber_smart_record</i>';
if (item.Type === 'SeriesTimer') {
return '<i class="md-icon timerIndicator indicatorIcon">&#xE062;</i>';
} }
if (item.TimerId) { else if (item.TimerId || item.SeriesTimerId) {
return '<i class="md-icon timerIndicator indicatorIcon">fiber_manual_record</i>';
status = item.Status || 'Cancelled';
}
else if (item.Type === 'Timer') {
status = item.Status;
}
else {
return '';
} }
return ''; if (item.SeriesTimerId) {
if (status !== 'Cancelled') {
return '<i class="md-icon timerIndicator indicatorIcon">&#xE062;</i>';
}
return '<i class="md-icon timerIndicator timerIndicator-inactive indicatorIcon">&#xE062;</i>';
}
return '<i class="md-icon timerIndicator indicatorIcon">&#xE061;</i>';
} }
function getSyncIndicator(item) { function getSyncIndicator(item) {
if (item.SyncPercent == 100) { if (item.SyncPercent === 100) {
return '<div class="syncIndicator indicator fullSyncIndicator"><i class="md-icon indicatorIcon">file_download</i></div>'; return '<div class="syncIndicator indicator fullSyncIndicator"><i class="md-icon indicatorIcon">file_download</i></div>';
} else if (item.SyncPercent != null) { } else if (item.SyncPercent != null) {
return '<div class="syncIndicator indicator emptySyncIndicator"><i class="md-icon indicatorIcon">file_download</i></div>'; return '<div class="syncIndicator indicator emptySyncIndicator"><i class="md-icon indicatorIcon">file_download</i></div>';

View file

@ -153,6 +153,12 @@ define(['playbackManager', 'focusManager', 'embyRouter', 'dom'], function (playb
case 'togglemute': case 'togglemute':
playbackManager.toggleMute(); playbackManager.toggleMute();
break; break;
case 'channelup':
playbackManager.nextTrack();
break;
case 'channeldown':
playbackManager.previousTrack();
break;
case 'volumedown': case 'volumedown':
playbackManager.volumeDown(); playbackManager.volumeDown();
break; break;

View file

@ -29,25 +29,47 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'embyRouter',
}); });
} }
if (item.Type == 'Timer' && user.Policy.EnableLiveTvManagement) { if ((item.Type == 'Timer') && user.Policy.EnableLiveTvManagement && options.cancelTimer !== false) {
commands.push({ commands.push({
name: globalize.translate('sharedcomponents#ButtonCancel'), name: globalize.translate('sharedcomponents#CancelRecording'),
id: 'canceltimer' id: 'canceltimer'
}); });
} }
if (item.CanDelete) { if ((item.Type == 'Recording' && item.Status == 'InProgress') && user.Policy.EnableLiveTvManagement && options.cancelTimer !== false) {
commands.push({ commands.push({
name: globalize.translate('sharedcomponents#Delete'), name: globalize.translate('sharedcomponents#CancelRecording'),
id: 'delete' id: 'canceltimer'
}); });
} }
if (itemHelper.canEdit(user, item.Type)) { if ((item.Type == 'SeriesTimer') && user.Policy.EnableLiveTvManagement && options.cancelTimer !== false) {
commands.push({
name: globalize.translate('sharedcomponents#CancelSeries'),
id: 'cancelseriestimer'
});
}
if (options.edit !== false) { if (item.CanDelete) {
var text = item.Type == 'Timer' ? globalize.translate('sharedcomponents#Edit') : globalize.translate('sharedcomponents#EditInfo'); if (item.Type == 'Playlist' || item.Type == 'BoxSet') {
commands.push({
name: globalize.translate('sharedcomponents#Delete'),
id: 'delete'
});
} else {
commands.push({
name: globalize.translate('sharedcomponents#DeleteMedia'),
id: 'delete'
});
}
}
if (itemHelper.canEdit(user, item)) {
if (options.edit !== false && item.Type != 'SeriesTimer') {
var text = (item.Type == 'Timer' || item.Type == 'SeriesTimer') ? globalize.translate('sharedcomponents#Edit') : globalize.translate('sharedcomponents#EditInfo');
commands.push({ commands.push({
name: text, name: text,
@ -56,7 +78,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'embyRouter',
} }
} }
if (itemHelper.canEditImages(user, item.Type)) { if (itemHelper.canEditImages(user, item)) {
if (options.editImages !== false) { if (options.editImages !== false) {
commands.push({ commands.push({
@ -66,9 +88,9 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'embyRouter',
} }
} }
if (itemHelper.canEdit(user, item.Type)) { if (itemHelper.canEdit(user, item)) {
if (item.MediaType == 'Video' && item.Type != 'TvChannel' && item.Type != 'Program' && item.LocationType != 'Virtual') { if (item.MediaType == 'Video' && item.Type != 'TvChannel' && item.Type != 'Program' && item.LocationType != 'Virtual' && !(item.Type == 'Recording' && item.Status != 'Completed')) {
if (options.editSubtitles !== false) { if (options.editSubtitles !== false) {
commands.push({ commands.push({
name: globalize.translate('sharedcomponents#EditSubtitles'), name: globalize.translate('sharedcomponents#EditSubtitles'),
@ -112,15 +134,6 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'embyRouter',
} }
} }
//if (options.open !== false) {
// if (item.Type != 'Timer' && item.Type != 'Audio') {
// commands.push({
// name: globalize.translate('sharedcomponents#Open'),
// id: 'open'
// });
// }
//}
if (canPlay) { if (canPlay) {
if (options.play !== false) { if (options.play !== false) {
commands.push({ commands.push({
@ -160,7 +173,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'embyRouter',
} }
} }
if (item.Type == 'Program' && (!item.TimerId && !item.SeriesTimerId)) { if (item.Type == 'Program') {
commands.push({ commands.push({
name: Globalize.translate('sharedcomponents#Record'), name: Globalize.translate('sharedcomponents#Record'),
@ -170,7 +183,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'embyRouter',
if (user.Policy.IsAdministrator) { if (user.Policy.IsAdministrator) {
if (item.Type != 'Timer' && item.Type != 'Program') { if (item.Type != 'Timer' && item.Type != 'SeriesTimer' && item.Type != 'Program' && !(item.Type == 'Recording' && item.Status != 'Completed')) {
commands.push({ commands.push({
name: globalize.translate('sharedcomponents#Refresh'), name: globalize.translate('sharedcomponents#Refresh'),
id: 'refresh' id: 'refresh'
@ -383,7 +396,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'embyRouter',
} }
case 'delete': case 'delete':
{ {
deleteItem(apiClient, itemId).then(getResolveFunction(resolve, id, true, true), getResolveFunction(resolve, id)); deleteItem(apiClient, item).then(getResolveFunction(resolve, id, true, true), getResolveFunction(resolve, id));
break; break;
} }
case 'share': case 'share':
@ -480,6 +493,9 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'embyRouter',
case 'canceltimer': case 'canceltimer':
deleteTimer(apiClient, item, resolve, id); deleteTimer(apiClient, item, resolve, id);
break; break;
case 'cancelseriestimer':
deleteSeriesTimer(apiClient, item, resolve, id);
break;
default: default:
reject(); reject();
break; break;
@ -489,21 +505,22 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'embyRouter',
function deleteTimer(apiClient, item, resolve, command) { function deleteTimer(apiClient, item, resolve, command) {
require(['confirm'], function (confirm) { require(['recordingHelper'], function (recordingHelper) {
confirm(globalize.translate('sharedcomponents#MessageConfirmRecordingCancellation'), globalize.translate('sharedcomponents#HeaderConfirmRecordingCancellation')).then(function () { var timerId = item.TimerId || item.Id;
loading.show(); recordingHelper.cancelTimerWithConfirmation(timerId, item.ServerId).then(function () {
getResolveFunction(resolve, command, true)();
});
});
}
apiClient.cancelLiveTvTimer(item.Id).then(function () { function deleteSeriesTimer(apiClient, item, resolve, command) {
require(['toast'], function (toast) { require(['recordingHelper'], function (recordingHelper) {
toast(globalize.translate('sharedcomponents#RecordingCancelled'));
});
loading.hide(); recordingHelper.cancelSeriesTimerWithConfirmation(item.Id, item.ServerId).then(function () {
getResolveFunction(resolve, command, true)(); getResolveFunction(resolve, command, true)();
});
}); });
}); });
} }
@ -539,6 +556,11 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'embyRouter',
if (item.Type == 'Timer') { if (item.Type == 'Timer') {
require(['recordingEditor'], function (recordingEditor) { require(['recordingEditor'], function (recordingEditor) {
recordingEditor.show(item.Id, serverId).then(resolve, reject);
});
} else if (item.Type == 'SeriesTimer') {
require(['seriesRecordingEditor'], function (recordingEditor) {
recordingEditor.show(item.Id, serverId).then(resolve, reject); recordingEditor.show(item.Id, serverId).then(resolve, reject);
}); });
} else { } else {
@ -550,16 +572,25 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'embyRouter',
}); });
} }
function deleteItem(apiClient, itemId) { function deleteItem(apiClient, item) {
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
var itemId = item.Id;
var msg = globalize.translate('sharedcomponents#ConfirmDeleteItem'); var msg = globalize.translate('sharedcomponents#ConfirmDeleteItem');
var title = globalize.translate('sharedcomponents#HeaderDeleteItem'); var title = globalize.translate('sharedcomponents#HeaderDeleteItem');
require(['confirm'], function (confirm) { require(['confirm'], function (confirm) {
confirm(msg, title).then(function () { confirm({
title: title,
text: msg,
confirmText: globalize.translate('sharedcomponents#Delete'),
primary: 'cancel'
}).then(function () {
apiClient.deleteItem(itemId).then(function () { apiClient.deleteItem(itemId).then(function () {
resolve(true); resolve(true);
@ -585,6 +616,10 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'embyRouter',
return getCommands(options).then(function (commands) { return getCommands(options).then(function (commands) {
if (!commands.length) {
return Promise.reject();
}
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
require(['actionsheet'], function (actionSheet) { require(['actionsheet'], function (actionSheet) {

View file

@ -8,7 +8,11 @@ define(['apphost'], function (appHost) {
options = options || {}; options = options || {};
var name = item.EpisodeTitle || item.Name || ''; if (item.Type == 'Timer') {
item = item.ProgramInfo || item;
}
var name = (item.Type == 'Program' && item.IsSeries ? item.EpisodeTitle : item.Name) || '';
if (item.Type == "TvChannel") { if (item.Type == "TvChannel") {
@ -37,7 +41,7 @@ define(['apphost'], function (appHost) {
number += "-" + displayIndexNumber; number += "-" + displayIndexNumber;
} }
name = number + " - " + name; name = name ? (number + " - " + name) : number;
} }
@ -46,26 +50,45 @@ define(['apphost'], function (appHost) {
function supportsAddingToCollection(item) { function supportsAddingToCollection(item) {
if (item.Type == 'Timer') { if (item.Type == 'Timer' || item.Type == 'SeriesTimer') {
return false; return false;
} }
var invalidTypes = ['Person', 'Genre', 'MusicGenre', 'Studio', 'GameGenre', 'BoxSet', 'Playlist', 'UserView', 'CollectionFolder', 'Audio', 'TvChannel', 'Program', 'MusicAlbum', 'Timer']; var invalidTypes = ['Person', 'Genre', 'MusicGenre', 'Studio', 'GameGenre', 'BoxSet', 'Playlist', 'UserView', 'CollectionFolder', 'Audio', 'TvChannel', 'Program', 'MusicAlbum', 'Timer'];
if (item.Type == 'Recording') {
if (item.Status != 'Completed') {
return false;
}
}
return !item.CollectionType && invalidTypes.indexOf(item.Type) == -1 && item.MediaType != 'Photo'; return !item.CollectionType && invalidTypes.indexOf(item.Type) == -1 && item.MediaType != 'Photo';
} }
function supportsAddingToPlaylist(item) { function supportsAddingToPlaylist(item) {
if (item.Type == 'Program') { if (item.Type == 'Program') {
return false; return false;
} }
if (item.Type == 'Timer') { if (item.Type == 'Timer') {
return false; return false;
} }
return item.RunTimeTicks || item.IsFolder || item.Type == "Genre" || item.Type == "MusicGenre" || item.Type == "MusicArtist"; if (item.Type == 'SeriesTimer') {
return false;
}
if (item.Type == 'Recording') {
if (item.Status != 'Completed') {
return false;
}
}
return item.MediaType || item.IsFolder || item.Type == "Genre" || item.Type == "MusicGenre" || item.Type == "MusicArtist";
} }
function canEdit(user, itemType) { function canEdit(user, item) {
var itemType = item.Type;
if (itemType == "UserRootFolder" || /*itemType == "CollectionFolder" ||*/ itemType == "UserView") { if (itemType == "UserRootFolder" || /*itemType == "CollectionFolder" ||*/ itemType == "UserView") {
return false; return false;
@ -75,12 +98,13 @@ define(['apphost'], function (appHost) {
return false; return false;
} }
if (user.Policy.IsAdministrator) { if (item.Type == 'Recording') {
if (item.Status != 'Completed') {
return true; return false;
}
} }
return false; return user.Policy.IsAdministrator;
} }
return { return {
@ -111,7 +135,9 @@ define(['apphost'], function (appHost) {
canEdit: canEdit, canEdit: canEdit,
canEditImages: function (user, itemType) { canEditImages: function (user, item) {
var itemType = item.Type;
if (itemType == 'UserView') { if (itemType == 'UserView') {
if (user.Policy.IsAdministrator) { if (user.Policy.IsAdministrator) {
@ -122,7 +148,13 @@ define(['apphost'], function (appHost) {
return false; return false;
} }
return itemType != 'Timer' && canEdit(user, itemType); if (item.Type == 'Recording') {
if (item.Status != 'Completed') {
return false;
}
}
return itemType != 'Timer' && itemType != 'SeriesTimer' && canEdit(user, item);
}, },
canSync: function (user, item) { canSync: function (user, item) {
@ -139,6 +171,14 @@ define(['apphost'], function (appHost) {
if (item.Type == 'Timer') { if (item.Type == 'Timer') {
return false; return false;
} }
if (item.Type == 'SeriesTimer') {
return false;
}
if (item.Type == 'Recording') {
if (item.Status != 'Completed') {
return false;
}
}
return user.Policy.EnablePublicSharing && appHost.supports('sharing'); return user.Policy.EnablePublicSharing && appHost.supports('sharing');
} }
}; };

View file

@ -77,7 +77,7 @@
var isPortrait = className.indexOf('portrait') != -1; var isPortrait = className.indexOf('portrait') != -1;
var parentName = isSmallItem || isMiniItem || isPortrait ? null : item.SeriesName; var parentName = isSmallItem || isMiniItem || isPortrait ? null : item.SeriesName;
var name = itemHelper.getDisplayName(item); var name = item.EpisodeTitle ? item.Name : itemHelper.getDisplayName(item);
html += '<div>'; html += '<div>';
var logoHeight = 26; var logoHeight = 26;
@ -140,13 +140,6 @@
html += '<button is="emby-button" class="itemAction autoSize fab cardOverlayFab mini" data-action="menu" data-playoptions="false"><i class="md-icon cardOverlayFab-md-icon">' + moreIcon + '</i></button>'; html += '<button is="emby-button" class="itemAction autoSize fab cardOverlayFab mini" data-action="menu" data-playoptions="false"><i class="md-icon cardOverlayFab-md-icon">' + moreIcon + '</i></button>';
buttonCount++; buttonCount++;
html += userdataButtons.getIconsHtml({
item: item,
style: 'fab-mini',
cssClass: 'cardOverlayFab',
iconCssClass: 'cardOverlayFab-md-icon'
});
html += '</div>'; html += '</div>';
html += '</div>'; html += '</div>';
@ -198,7 +191,7 @@
var id = dataElement.getAttribute('data-id'); var id = dataElement.getAttribute('data-id');
var type = dataElement.getAttribute('data-type'); var type = dataElement.getAttribute('data-type');
if (type == 'Timer') { if (type == 'Timer' || type == 'SeriesTimer') {
return; return;
} }
@ -215,6 +208,16 @@
innerElem.innerHTML = getOverlayHtml(apiClient, item, user, dataElement); innerElem.innerHTML = getOverlayHtml(apiClient, item, user, dataElement);
userdataButtons.fill({
item: item,
style: 'fab-mini',
cssClass: 'cardOverlayFab',
iconCssClass: 'cardOverlayFab-md-icon',
element: innerElem.querySelector('.cardOverlayButtons'),
fillMode: 'insertAdjacent',
insertLocation: 'beforeend'
});
innerElem.querySelector('.cardOverlayButtons').addEventListener('click', onCardOverlayButtonsClick); innerElem.querySelector('.cardOverlayButtons').addEventListener('click', onCardOverlayButtonsClick);
}); });
@ -243,7 +246,7 @@
showOverlayTimeout = setTimeout(function () { showOverlayTimeout = setTimeout(function () {
onShowTimerExpired(card); onShowTimerExpired(card);
}, 1000); }, 1400);
} }
function preventTouchHover() { function preventTouchHover() {

View file

@ -1,4 +1,5 @@
define(['browser', 'appSettings', 'events'], function (browser, appSettings, events) { define(['browser', 'appSettings', 'events'], function (browser, appSettings, events) {
'use strict';
function setLayout(self, layout, selectedLayout) { function setLayout(self, layout, selectedLayout) {
@ -17,7 +18,7 @@ define(['browser', 'appSettings', 'events'], function (browser, appSettings, eve
self.setLayout = function (layout, save) { self.setLayout = function (layout, save) {
if (!layout || layout == 'auto') { if (!layout || layout === 'auto') {
self.autoLayout(); self.autoLayout();
if (save !== false) { if (save !== false) {

View file

@ -15,19 +15,10 @@
overflow: hidden; overflow: hidden;
} }
.listItem-border {
border-bottom: 1px solid #2a2a2a;
}
.listItem-button { .listItem-button {
width: 100%; width: 100%;
} }
.listItem-nosidepadding {
padding-left: 0;
padding-right: 0;
}
.listItem-largeImage { .listItem-largeImage {
padding: .5em !important; padding: .5em !important;
} }
@ -46,6 +37,7 @@
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
flex-shrink: 0; flex-shrink: 0;
contain: layout style;
} }
.listViewDragHandle { .listViewDragHandle {
@ -54,33 +46,20 @@
.listItemBody { .listItemBody {
flex-grow: 1; flex-grow: 1;
padding: 0 1em; padding: .8em 1em;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
flex-direction: column; flex-direction: column;
vertical-align: middle; vertical-align: middle;
justify-content: center; justify-content: center;
min-height: 3.44em;
} }
.listItemBody-nogrow { .listItemBody-noleftpadding {
flex-grow: initial; padding-left: 0;
flex-shrink: 0;
width: 9em;
opacity: .7;
} }
@media all and (max-width: 800px) { .listItem-odd {
background: #1c1c1c;
.listItemBody-nogrow {
width: 4em;
}
}
.two-line {
min-height: 5.15em;
padding-top: 0;
padding-bottom: 0;
} }
.three-line { .three-line {
@ -128,7 +107,6 @@
background-color: #52B54B; background-color: #52B54B;
padding: .5em; padding: .5em;
color: #fff; color: #fff;
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12), 0 3px 1px -2px rgba(0, 0, 0, 0.2);
} }
.listItemProgressBar { .listItemProgressBar {
@ -169,6 +147,7 @@
/* Don't display if flex not supported */ /* Don't display if flex not supported */
display: none; display: none;
align-items: center; align-items: center;
margin-right: 1em;
} }
.listGroupHeader { .listGroupHeader {
@ -191,6 +170,7 @@
.listItem, .listItemBody, .listItemMediaInfo { .listItem, .listItemBody, .listItemMediaInfo {
display: flex; display: flex;
contain: layout style;
} }
} }
@ -200,3 +180,7 @@
display: none !important; display: none !important;
} }
} }
.listItemCheckboxContainer {
width: auto !important;
}

View file

@ -111,6 +111,12 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
for (var i = 0, length = textlines.length; i < length; i++) { for (var i = 0, length = textlines.length; i < length; i++) {
var text = textlines[i];
if (!text) {
continue;
}
if (i === 0) { if (i === 0) {
if (isLargeStyle) { if (isLargeStyle) {
html += '<h2 class="listItemBodyText">'; html += '<h2 class="listItemBodyText">';
@ -143,7 +149,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
var clickEntireItem = layoutManager.tv ? true : false; var clickEntireItem = layoutManager.tv ? true : false;
var outerTagName = clickEntireItem ? 'button' : 'div'; var outerTagName = clickEntireItem ? 'button' : 'div';
var enableSideMediaInfo = options.enableSideMediaInfo != null ? options.enableSideMediaInfo : clickEntireItem; var enableSideMediaInfo = options.enableSideMediaInfo != null ? options.enableSideMediaInfo : true;
var outerHtml = ''; var outerHtml = '';
@ -178,10 +184,12 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
} }
} }
var cssClass = "listItem listItem-nosidepadding"; var cssClass = "listItem";
if (options.border !== false) { if (options.highlight !== false) {
cssClass += ' listItem-border'; if (i % 2 == 1) {
cssClass += ' listItem-odd';
}
} }
if (clickEntireItem) { if (clickEntireItem) {
@ -242,23 +250,32 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
html += '</div>'; html += '</div>';
} }
if (options.showProgramTimeColumn) { var textlines = [];
html += '<div class="listItemBody listItemBody-nogrow listItemBody-rightborder"><div class="listItemBodyText">';
html += datetime.getDisplayTime(datetime.parseISO8601Date(item.StartDate)); if (options.showProgramDateTime) {
html += ' - '; textlines.push(datetime.toLocaleString(datetime.parseISO8601Date(item.StartDate), {
html += datetime.getDisplayTime(datetime.parseISO8601Date(item.EndDate));
html += '</div></div>'; weekday: 'long',
month: 'short',
day: 'numeric',
hour: 'numeric',
minute: '2-digit'
}));
} }
var textlines = []; if (options.showProgramTime) {
textlines.push(datetime.getDisplayTime(datetime.parseISO8601Date(item.StartDate)));
}
var parentTitle = null;
if (options.showParentTitle) { if (options.showParentTitle) {
if (item.Type == 'Episode') { if (item.Type == 'Episode') {
textlines.push(item.SeriesName || '&nbsp;'); parentTitle = item.SeriesName;
} }
if (item.EpisodeTitle) { else if (item.IsSeries) {
textlines.push(item.Name || '&nbsp;'); parentTitle = item.Name;
} }
} }
@ -267,21 +284,42 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
if (options.showIndexNumber && item.IndexNumber != null) { if (options.showIndexNumber && item.IndexNumber != null) {
displayName = item.IndexNumber + ". " + displayName; displayName = item.IndexNumber + ". " + displayName;
} }
textlines.push(displayName);
if (item.ArtistItems && item.Type != 'MusicAlbum') { if (options.showParentTitle && options.parentTitleWithTitle) {
textlines.push(item.ArtistItems.map(function (a) {
return a.Name;
}).join(', ') || '&nbsp;'); if (displayName) {
if (parentTitle) {
parentTitle += ' - ';
}
parentTitle = (parentTitle || '') + displayName;
}
textlines.push(parentTitle || '');
}
else if (options.showParentTitle) {
textlines.push(parentTitle || '');
} }
if (item.AlbumArtist && item.Type == 'MusicAlbum') { if (displayName && !options.parentTitleWithTitle) {
textlines.push(item.AlbumArtist || '&nbsp;'); textlines.push(displayName);
}
if (options.artist !== false) {
if (item.ArtistItems && item.Type != 'MusicAlbum') {
textlines.push(item.ArtistItems.map(function (a) {
return a.Name;
}).join(', '));
}
if (item.AlbumArtist && item.Type == 'MusicAlbum') {
textlines.push(item.AlbumArtist);
}
} }
if (item.Type == 'Game') { if (item.Type == 'Game') {
textlines.push(item.GameSystem || '&nbsp;'); textlines.push(item.GameSystem);
} }
if (item.Type == 'TvChannel') { if (item.Type == 'TvChannel') {
@ -291,24 +329,31 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
} }
} }
cssClass = 'listItemBody two-line'; cssClass = 'listItemBody';
if (!clickEntireItem) { if (!clickEntireItem) {
cssClass += ' itemAction'; cssClass += ' itemAction';
} }
if (options.image === false) {
cssClass += ' itemAction listItemBody-noleftpadding';
}
html += '<div class="' + cssClass + '">'; html += '<div class="' + cssClass + '">';
var moreIcon = appHost.moreIcon == 'dots-horiz' ? '&#xE5D3;' : '&#xE5D4;'; var moreIcon = appHost.moreIcon == 'dots-horiz' ? '&#xE5D3;' : '&#xE5D4;';
html += getTextLinesHtml(textlines, isLargeStyle); html += getTextLinesHtml(textlines, isLargeStyle);
if (!enableSideMediaInfo) { if (options.mediaInfo !== false) {
if (!enableSideMediaInfo) {
var mediaInfoClass = 'secondary listItemMediaInfo listItemBodyText'; var mediaInfoClass = 'secondary listItemMediaInfo listItemBodyText';
html += '<div class="' + mediaInfoClass + '">' + mediaInfo.getPrimaryMediaInfoHtml(item, { html += '<div class="' + mediaInfoClass + '">' + mediaInfo.getPrimaryMediaInfoHtml(item, {
episodeTitle: false episodeTitle: false,
}) + '</div>'; originalAirDate: false
}) + '</div>';
}
} }
if (enableOverview && item.Overview) { if (enableOverview && item.Overview) {
@ -319,18 +364,32 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
html += '</div>'; html += '</div>';
if (enableSideMediaInfo) { if (options.mediaInfo !== false) {
html += '<div class="secondary listItemMediaInfo">' + mediaInfo.getPrimaryMediaInfoHtml(item, { if (enableSideMediaInfo) {
html += '<div class="secondary listItemMediaInfo">' + mediaInfo.getPrimaryMediaInfoHtml(item, {
year: false, year: false,
container: false, container: false,
episodeTitle: false episodeTitle: false
}) + '</div>'; }) + '</div>';
}
}
if (!options.recordButton && (item.Type == 'Timer' || item.Type == 'Program')) {
html += indicators.getTimerIndicator(item).replace('indicatorIcon', 'indicatorIcon listItemAside');
} }
if (!clickEntireItem) { if (!clickEntireItem) {
html += '<button is="paper-icon-button-light" class="listItemButton itemAction autoSize" data-action="menu"><i class="md-icon">' + moreIcon + '</i></button>';
if (options.moreButton !== false) {
html += '<button is="paper-icon-button-light" class="listItemButton itemAction autoSize" data-action="menu"><i class="md-icon">' + moreIcon + '</i></button>';
}
if (options.recordButton) {
html += '<button is="paper-icon-button-light" class="listItemButton itemAction autoSize" data-action="programdialog">' + indicators.getTimerIndicator(item) + '</button>';
}
if (options.enableUserDataButtons !== false) { if (options.enableUserDataButtons !== false) {
html += '<span class="listViewUserDataButtons">'; html += '<span class="listViewUserDataButtons">';

View file

@ -54,7 +54,6 @@
.mediaInfoProgramAttribute { .mediaInfoProgramAttribute {
color: #fff; color: #fff;
text-transform: uppercase; text-transform: uppercase;
background: #EF6C00;
padding: .16em .6em; padding: .16em .6em;
border-radius: .15em; border-radius: .15em;
font-size: 80%; font-size: 80%;

View file

@ -1,4 +1,35 @@
define(['datetime', 'globalize', 'embyRouter', 'itemHelper', 'material-icons', 'css!./mediainfo.css'], function (datetime, globalize, embyRouter, itemHelper) { define(['datetime', 'globalize', 'embyRouter', 'itemHelper', 'material-icons', 'css!./mediainfo.css', 'programStyles'], function (datetime, globalize, embyRouter, itemHelper) {
function getTimerIndicator(item) {
var status;
if (item.Type == 'SeriesTimer') {
return '<i class="md-icon mediaInfoItem mediaInfoIconItem mediaInfoTimerIcon">&#xE062;</i>';
}
else if (item.TimerId || item.SeriesTimerId) {
status = item.Status || 'Cancelled';
}
else if (item.Type == 'Timer') {
status = item.Status;
}
else {
return '';
}
if (item.SeriesTimerId) {
if (status != 'Cancelled') {
return '<i class="md-icon mediaInfoItem mediaInfoIconItem mediaInfoTimerIcon">&#xE062;</i>';
}
return '<i class="md-icon mediaInfoItem mediaInfoIconItem">&#xE062;</i>';
}
return '<i class="md-icon mediaInfoItem mediaInfoIconItem mediaInfoTimerIcon">&#xE061;</i>';
}
function getProgramInfoHtml(item, options) { function getProgramInfoHtml(item, options) {
var html = ''; var html = '';
@ -6,23 +37,14 @@ define(['datetime', 'globalize', 'embyRouter', 'itemHelper', 'material-icons', '
var miscInfo = []; var miscInfo = [];
var text, date; var text, date;
if (item.ChannelName) {
if (options.interactive && item.ChannelId) {
miscInfo.push('<a class="lnkChannel" data-id="' + item.ChannelId + '" data-serverid="' + item.ServerId + '" href="#">' + item.ChannelName + '</a>');
} else {
miscInfo.push(item.ChannelName);
}
}
if (item.StartDate) { if (item.StartDate) {
try { try {
date = datetime.parseISO8601Date(item.StartDate); date = datetime.parseISO8601Date(item.StartDate);
text = datetime.toLocaleDateString(date); text = datetime.toLocaleDateString(date, { weekday: 'short', month: 'short', day: 'numeric' });
text += ', ' + datetime.getDisplayTime(date); text += ' ' + datetime.getDisplayTime(date);
if (item.EndDate) { if (item.EndDate) {
date = datetime.parseISO8601Date(item.EndDate); date = datetime.parseISO8601Date(item.EndDate);
@ -40,15 +62,22 @@ define(['datetime', 'globalize', 'embyRouter', 'itemHelper', 'material-icons', '
miscInfo.push('CH ' + item.ChannelNumber); miscInfo.push('CH ' + item.ChannelNumber);
} }
if (item.SeriesTimerId) { if (item.ChannelName) {
miscInfo.push({
html: '<i class="md-icon mediaInfoItem mediaInfoTimerIcon mediaInfoIconItem">&#xE062;</i>' if (options.interactive && item.ChannelId) {
}); miscInfo.push('<a class="lnkChannel" data-id="' + item.ChannelId + '" data-serverid="' + item.ServerId + '" href="#">' + item.ChannelName + '</a>');
} else {
miscInfo.push(item.ChannelName);
}
} }
else if (item.TimerId) {
miscInfo.push({ if (options.timerIndicator !== false) {
html: '<i class="md-icon mediaInfoItem mediaInfoTimerIcon mediaInfoIconItem">&#xE061;</i>' var timerHtml = getTimerIndicator(item);
}); if (timerHtml) {
miscInfo.push({
html: timerHtml
});
}
} }
html += miscInfo.map(function (m) { html += miscInfo.map(function (m) {
@ -159,22 +188,22 @@ define(['datetime', 'globalize', 'embyRouter', 'itemHelper', 'material-icons', '
if (item.IsLive) { if (item.IsLive) {
miscInfo.push({ miscInfo.push({
html: '<div class="mediaInfoProgramAttribute mediaInfoItem">' + globalize.translate('sharedcomponents#Live') + '</div>' html: '<div class="mediaInfoProgramAttribute mediaInfoItem liveTvProgram">' + globalize.translate('sharedcomponents#Live') + '</div>'
}); });
} }
else if (item.IsPremiere) { else if (item.IsPremiere) {
miscInfo.push({ miscInfo.push({
html: '<div class="mediaInfoProgramAttribute mediaInfoItem">' + globalize.translate('sharedcomponents#Premiere') + '</div>' html: '<div class="mediaInfoProgramAttribute mediaInfoItem premiereTvProgram">' + globalize.translate('sharedcomponents#Premiere') + '</div>'
}); });
} }
else if (item.IsSeries && !item.IsRepeat) { else if (item.IsSeries && !item.IsRepeat) {
miscInfo.push({ miscInfo.push({
html: '<div class="mediaInfoProgramAttribute mediaInfoItem">' + globalize.translate('sharedcomponents#AttributeNew') + '</div>' html: '<div class="mediaInfoProgramAttribute mediaInfoItem newTvProgram">' + globalize.translate('sharedcomponents#AttributeNew') + '</div>'
}); });
} }
else if (item.IsSeries && item.IsRepeat) { else if (item.IsSeries && item.IsRepeat) {
miscInfo.push({ miscInfo.push({
html: '<div class="mediaInfoProgramAttribute mediaInfoItem">' + globalize.translate('sharedcomponents#Repeat') + '</div>' html: '<div class="mediaInfoProgramAttribute mediaInfoItem repeatTvProgram">' + globalize.translate('sharedcomponents#Repeat') + '</div>'
}); });
} }
@ -182,7 +211,7 @@ define(['datetime', 'globalize', 'embyRouter', 'itemHelper', 'material-icons', '
miscInfo.push(itemHelper.getDisplayName(item)); miscInfo.push(itemHelper.getDisplayName(item));
} }
else if (item.PremiereDate) { else if (item.PremiereDate && options.originalAirDate !== false) {
try { try {
date = datetime.parseISO8601Date(item.PremiereDate); date = datetime.parseISO8601Date(item.PremiereDate);
@ -198,20 +227,22 @@ define(['datetime', 'globalize', 'embyRouter', 'itemHelper', 'material-icons', '
} }
} }
if (item.Type != "Series" && item.Type != "Episode" && item.Type != "Person" && item.MediaType != 'Photo' && item.Type != 'Program') { if (options.year !== false) {
if (item.Type != "Series" && item.Type != "Episode" && item.Type != "Person" && item.MediaType != 'Photo' && item.Type != 'Program') {
if (item.ProductionYear) { if (item.ProductionYear) {
miscInfo.push(item.ProductionYear); miscInfo.push(item.ProductionYear);
}
else if (item.PremiereDate) {
try {
text = datetime.parseISO8601Date(item.PremiereDate).getFullYear();
miscInfo.push(text);
} }
catch (e) { else if (item.PremiereDate) {
console.log("Error parsing date: " + item.PremiereDate);
try {
text = datetime.parseISO8601Date(item.PremiereDate).getFullYear();
miscInfo.push(text);
}
catch (e) {
console.log("Error parsing date: " + item.PremiereDate);
}
} }
} }
} }

View file

@ -156,7 +156,6 @@
AirDays: getSelectedAirDays(form), AirDays: getSelectedAirDays(form),
AirTime: form.querySelector('#txtAirTime').value, AirTime: form.querySelector('#txtAirTime').value,
Genres: editableListViewValues(form.querySelector("#listGenres")), Genres: editableListViewValues(form.querySelector("#listGenres")),
ProductionLocations: editableListViewValues(form.querySelector("#listCountries")),
Tags: editableListViewValues(form.querySelector("#listTags")), Tags: editableListViewValues(form.querySelector("#listTags")),
Keywords: editableListViewValues(form.querySelector("#listKeywords")), Keywords: editableListViewValues(form.querySelector("#listKeywords")),
Studios: editableListViewValues(form.querySelector("#listStudios")).map(function (element) { return { Name: element }; }), Studios: editableListViewValues(form.querySelector("#listStudios")).map(function (element) { return { Name: element }; }),
@ -683,12 +682,6 @@
showElement('#fldCustomRating', context); showElement('#fldCustomRating', context);
} }
if (item.Type == "Movie" || item.Type == "Trailer" || item.Type == "MusicArtist") {
showElement('#countriesCollapsible', context);
} else {
hideElement('#countriesCollapsible', context);
}
if (item.Type == "TvChannel") { if (item.Type == "TvChannel") {
hideElement('#tagsCollapsible', context); hideElement('#tagsCollapsible', context);
hideElement('#metadataSettingsCollapsible', context); hideElement('#metadataSettingsCollapsible', context);
@ -809,7 +802,6 @@
el.checked = (item.AirDays || []).indexOf(el.getAttribute('data-day')) != -1; el.checked = (item.AirDays || []).indexOf(el.getAttribute('data-day')) != -1;
}); });
populateListView(context.querySelector('#listCountries'), item.ProductionLocations || []);
populateListView(context.querySelector('#listGenres'), item.Genres); populateListView(context.querySelector('#listGenres'), item.Genres);
populatePeople(context, item.People || []); populatePeople(context, item.People || []);

Some files were not shown because too many files have changed in this diff Show more