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 class="content-primary">
@ -27,7 +27,7 @@
<p id="btnInstallDiv" class="hide">
<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>
</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="return" id="paypalReturnUrl" value="#">
<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>
</button>
@ -78,14 +77,6 @@
</div>
<br />
<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 class="collapseContent">
<p id="developer"></p>

View file

@ -6,7 +6,6 @@
<p>${AutoOrganizeHelp}</p>
<p>${AutoOrganizeTvHelp}</p>
<div>
<label class="checkboxContainer">
<input type="checkbox" is="emby-checkbox" id="chkEnableTvSorting" />
@ -19,7 +18,7 @@
<input is="emby-input" id="txtWatchFolder" type="text" label="${LabelWatchFolder}" />
<div class="fieldDescription">${LabelWatchFolderHelp}</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 class="inputContainer">
@ -35,8 +34,6 @@
<div class="fieldDescription"></div>
</div>
<br />
<div is="emby-collapse" title="${HeaderEpisodeFilePattern}">
<div class="collapseContent">
<br />
@ -157,7 +154,7 @@
<div class="fieldDescription checkboxFieldDescription">${LabelDeleteEmptyFoldersHelp}</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>
</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": {},
"ignore": [],
"version": "1.1.79",
"_release": "1.1.79",
"version": "1.1.87",
"_release": "1.1.87",
"_resolution": {
"type": "version",
"tag": "1.1.79",
"commit": "bec0b71fec80821578400743ad836ce1a05c0c00"
"tag": "1.1.87",
"commit": "21057764cdf82e9ef08514cca4e48c76d47e535f"
},
"_source": "https://github.com/MediaBrowser/Emby.ApiClient.Javascript.git",
"_target": "^1.1.51",

View file

@ -1,4 +1,5 @@
define(['events'], function (events) {
'use strict';
/**
* Creates a new api client instance
@ -29,11 +30,11 @@
if (val != null) {
if (val.toLowerCase().indexOf('http') != 0) {
if (val.toLowerCase().indexOf('http') !== 0) {
throw new Error('Invalid url: ' + val);
}
var changed = val != serverAddress;
var changed = val !== serverAddress;
serverAddress = val;
@ -189,7 +190,7 @@
var headers = request.headers || {};
if (request.dataType == 'json') {
if (request.dataType === 'json') {
headers.accept = 'application/json';
}
@ -274,16 +275,16 @@
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);
return getFetchPromise(request).then(function (response) {
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();
} 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();
} else {
return response;
@ -349,7 +350,7 @@
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", {
@ -406,9 +407,9 @@
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();
} 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();
} else {
return response;
@ -478,11 +479,11 @@
throw new Error("serverAddress is yet not set");
}
var lowered = url.toLowerCase();
if (lowered.indexOf('/emby') == -1 && lowered.indexOf('/mediabrowser') == -1) {
if (lowered.indexOf('/emby') === -1 && lowered.indexOf('/mediabrowser') === -1) {
url += '/emby';
}
if (name.charAt(0) != '/') {
if (name.charAt(0) !== '/') {
url += '/';
}
@ -535,7 +536,11 @@
return;
}
self.openWebSocket();
try {
self.openWebSocket();
} catch (err) {
console.log("Error opening web socket: " + err);
}
};
function replaceAll(originalString, strReplace, strWith) {
@ -598,7 +603,7 @@
else if (msg.MessageType === "UserUpdated" || msg.MessageType === "UserConfigurationUpdated") {
var user = msg.Data;
if (user.Id == self.getCurrentUserId()) {
if (user.Id === self.getCurrentUserId()) {
currentUser = null;
}
@ -670,13 +675,13 @@
return self.getDownloadSpeed(1000000).then(function (bitrate) {
if (bitrate < 1000000) {
return Math.round(bitrate * .8);
return Math.round(bitrate * 0.8);
} else {
// 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 Math.round(bitrate * .8);
return Math.round(bitrate * 0.8);
});
}
@ -1735,7 +1740,7 @@
* Adds a virtual folder
* @param {String} name
*/
self.addVirtualFolder = function (name, type, refreshLibrary, initialPaths, libraryOptions) {
self.addVirtualFolder = function (name, type, refreshLibrary, libraryOptions) {
if (!name) {
throw new Error("null name");
@ -1758,7 +1763,6 @@
type: "POST",
url: url,
data: JSON.stringify({
Paths: initialPaths,
LibraryOptions: libraryOptions
}),
contentType: 'application/json'
@ -1813,7 +1817,7 @@
* Adds an additional mediaPath to an existing virtual folder
* @param {String} name
*/
self.addMediaPath = function (virtualFolderName, mediaPath, refreshLibrary) {
self.addMediaPath = function (virtualFolderName, mediaPath, networkSharePath, refreshLibrary) {
if (!virtualFolderName) {
throw new Error("null virtualFolderName");
@ -1825,15 +1829,50 @@
var url = "Library/VirtualFolders/Paths";
var pathInfo = {
Path: mediaPath
};
if (networkSharePath) {
pathInfo.NetworkPath = networkSharePath;
}
url = self.getUrl(url, {
refreshLibrary: refreshLibrary ? true : false,
path: mediaPath,
name: virtualFolderName
refreshLibrary: refreshLibrary ? true : false
});
return self.ajax({
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.");
}
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.");
}
@ -2092,7 +2131,7 @@
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.");
}
@ -2326,7 +2365,7 @@
};
self.getDefaultImageQuality = function (imageType) {
return imageType.toLowerCase() == 'backdrop' ? 80 : 90;
return imageType.toLowerCase() === 'backdrop' ? 80 : 90;
};
function normalizeImageOptions(options) {
@ -2866,7 +2905,7 @@
var url;
if ((typeof userId).toString().toLowerCase() == 'string') {
if ((typeof userId).toString().toLowerCase() === 'string') {
url = self.getUrl("Users/" + userId + "/Items", options);
} else {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,4 +1,5 @@
define([], function () {
'use strict';
function stringToArrayBuffer(string) {
// UTF-16LE
@ -79,7 +80,7 @@
console.log(info);
if (info != null && info.socketId == socketId) {
if (info != null && info.socketId === socketId) {
var json = arrayBufferToString(info.data);
console.log('Server discovery json: ' + json);
var server = JSON.parse(json);
@ -119,7 +120,7 @@
console.log('chrome.sockets.udp.bind');
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);
return;
}
@ -130,7 +131,7 @@
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);
} else {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,4 +1,5 @@
define([], function () {
'use strict';
return function (connectionManager) {
@ -20,7 +21,7 @@
return connectionManager.connectToServer(server, connectionOptions).then(function (result) {
if (result.State == MediaBrowser.ConnectionState.SignedIn) {
if (result.State === MediaBrowser.ConnectionState.SignedIn) {
return performSync(server, options);
} else {
console.log('Unable to connect to server id: ' + server.Id);
@ -42,7 +43,7 @@
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;
}

View file

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

View file

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

View file

@ -4,10 +4,21 @@
padding: 0;
border: none;
max-height: 84%;
border-radius: 1px !important;
color: #fff;
}
.actionsheet-not-fullscreen {
background-color: #2a2a2a;
}
.actionSheetMenuItem:hover {
background-color: #333;
}
.actionsheet-fullscreen {
max-height: none;
border-radius: 0 !important;
}
.actionSheetContent-centered {
@ -35,6 +46,8 @@
font-weight: inherit;
align-items: center;
flex-shrink: 0;
background: transparent;
box-shadow: none;
}
.actionSheetMenuItem-noflex {
@ -94,4 +107,4 @@
position: fixed;
top: .75em;
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) {
'use strict';
function getOffsets(elems) {
@ -25,7 +26,9 @@
results[i] = {
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];
if (options.positionY != 'top') {
pos.top += options.positionTo.offsetHeight / 2;
if (options.positionY !== 'top') {
pos.top += (pos.height || 0) / 2;
}
pos.left += options.positionTo.offsetWidth / 2;
pos.left += (pos.width || 0) / 2;
var height = dlg.offsetHeight || 300;
var width = dlg.offsetWidth || 160;
@ -119,6 +122,8 @@
if (isFullscreen) {
dlg.classList.add('actionsheet-fullscreen');
} else {
dlg.classList.add('actionsheet-not-fullscreen');
}
var extraSpacing = !layoutManager.tv;

View file

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

View file

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

View file

@ -1,14 +1,16 @@
define(['focusManager', 'css!./style.css', 'paper-icon-button-light', 'material-icons'], function (focusManager) {
'use strict';
var selectedButtonClass = 'alphaPickerButton-selected';
function focus() {
var selected = this.querySelector('.' + selectedButtonClass);
var scope = this;
var selected = scope.querySelector('.' + selectedButtonClass);
if (selected) {
focusManager.focus(selected);
} 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;
html += '<div class="alphaPickerRow">';
if (options.mode == 'keyboard') {
if (options.mode === 'keyboard') {
// space_bar icon
html += '<button data-value=" " is="paper-icon-button-light" class="alphaPickerButton autoSize">\
<i class="md-icon alphaPickerButtonIcon">&#xE256;</i>\
</button>';
html += '<button data-value=" " is="paper-icon-button-light" class="alphaPickerButton autoSize"><i class="md-icon alphaPickerButtonIcon">&#xE256;</i></button>';
} else {
letters = ['#'];
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'];
html += letters.map(getLetterButton).join('');
if (options.mode == 'keyboard') {
if (options.mode === 'keyboard') {
// backspace icon
html += '<button data-value="backspace" is="paper-icon-button-light" class="alphaPickerButton autoSize">\
<i class="md-icon alphaPickerButtonIcon">&#xE14A;</i>\
</button>';
html += '<button data-value="backspace" is="paper-icon-button-light" class="alphaPickerButton autoSize"><i class="md-icon alphaPickerButtonIcon">&#xE14A;</i></button>';
html += '</div>';
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;
}
function alphaPicker(options) {
function AlphaPicker(options) {
var self = this;
@ -83,7 +81,7 @@ define(['focusManager', 'css!./style.css', 'paper-icon-button-light', 'material-
alphaFocusTimeout = null;
if (document.activeElement == alphaFocusedElement) {
if (document.activeElement === alphaFocusedElement) {
var value = alphaFocusedElement.getAttribute('data-value');
self.value(value, true);
}
@ -125,7 +123,7 @@ define(['focusManager', 'css!./style.css', 'paper-icon-button-light', 'material-
if (alphaPickerButton) {
var value = alphaPickerButton.getAttribute('data-value');
if (currentValue == value.toUpperCase()) {
if (currentValue === value.toUpperCase()) {
self.value(null, true);
} else {
self.value(value, true);
@ -173,7 +171,7 @@ define(['focusManager', 'css!./style.css', 'paper-icon-button-light', 'material-
itemsContainer.addEventListener('focus', onItemsFocusIn, true);
}
if (options.mode == 'keyboard') {
if (options.mode === 'keyboard') {
element.addEventListener('click', onAlphaPickerInKeyboardModeClick);
}
@ -225,14 +223,14 @@ define(['focusManager', 'css!./style.css', 'paper-icon-button-light', 'material-
value = value.toUpperCase();
currentValue = value;
if (options.mode != 'keyboard') {
if (options.mode !== 'keyboard') {
selected = element.querySelector('.' + selectedButtonClass);
btn = element.querySelector('.alphaPickerButton[data-value=\'' + value + '\']');
if (btn && btn != selected) {
if (btn && btn !== selected) {
btn.classList.add(selectedButtonClass);
}
if (selected && selected != btn) {
if (selected && selected !== btn) {
selected.classList.remove(selectedButtonClass);
}
}
@ -281,5 +279,5 @@ define(['focusManager', 'css!./style.css', 'paper-icon-button-light', 'material-
self.visible(true);
}
return alphaPicker;
return AlphaPicker;
});

View file

@ -1,4 +1,5 @@
define(['appStorage', 'events'], function (appStorage, events) {
'use strict';
function getKey(name, userId) {
@ -9,7 +10,7 @@ define(['appStorage', 'events'], function (appStorage, events) {
return name;
}
return new function () {
function AppSettings() {
var self = this;
@ -19,7 +20,7 @@ define(['appStorage', 'events'], function (appStorage, events) {
self.set('enableAutoLogin', val.toString());
}
return self.get('enableAutoLogin') != 'false';
return self.get('enableAutoLogin') !== 'false';
};
self.enableAutomaticBitrateDetection = function (val) {
@ -28,7 +29,7 @@ define(['appStorage', 'events'], function (appStorage, events) {
self.set('enableAutomaticBitrateDetection', val.toString());
}
return self.get('enableAutomaticBitrateDetection') != 'false';
return self.get('enableAutomaticBitrateDetection') !== 'false';
};
self.maxStreamingBitrate = function (val) {
@ -66,7 +67,7 @@ define(['appStorage', 'events'], function (appStorage, events) {
self.set('syncOnlyOnWifi', val.toString());
}
return self.get('syncOnlyOnWifi') != 'false';
return self.get('syncOnlyOnWifi') !== 'false';
};
self.syncPath = function (val) {
@ -99,7 +100,7 @@ define(['appStorage', 'events'], function (appStorage, events) {
appStorage.setItem(getKey(name, userId), value);
if (currentValue != value) {
if (currentValue !== value) {
events.trigger(self, 'change', [name]);
}
};
@ -108,5 +109,7 @@ define(['appStorage', 'events'], function (appStorage, events) {
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) {
'use strict';
function enableAnimation(elem) {
@ -18,7 +19,7 @@
return true;
}
function backdrop() {
function Backdrop() {
var self = this;
var isDestroyed;
@ -52,7 +53,7 @@
currentAnimation = animation;
animation.onfinish = function () {
if (animation == currentAnimation) {
if (animation === currentAnimation) {
currentAnimation = null;
}
if (existingBackdropImage && existingBackdropImage.parentNode) {
@ -166,14 +167,14 @@
var elem = getBackdropContainer();
var existingBackdropImage = elem.querySelector('.displayingBackdropImage');
if (existingBackdropImage && existingBackdropImage.getAttribute('data-url') == url) {
if (existingBackdropImage.getAttribute('data-url') == url) {
if (existingBackdropImage && existingBackdropImage.getAttribute('data-url') === url) {
if (existingBackdropImage.getAttribute('data-url') === url) {
return;
}
existingBackdropImage.classList.remove('displayingBackdropImage');
}
var instance = new backdrop();
var instance = new Backdrop();
instance.load(url, elem, existingBackdropImage);
currentLoadingBackdrop = instance;
}
@ -215,28 +216,38 @@
var list = [];
var onImg = function (img) {
list.push(img);
};
for (var i = 0, length = items.length; i < length; i++) {
var itemImages = getItemImageUrls(items[i]);
itemImages.forEach(function (img) {
list.push(img);
});
itemImages.forEach(onImg);
}
return list;
}
function arraysEqual(a, b) {
if (a === b) return true;
if (a == null || b == null) return false;
if (a.length != b.length) return false;
if (a === b) {
return true;
}
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
// the array, you should sort both arrays here.
for (var i = 0; i < a.length; ++i) {
if (a[i] !== b[i]) return false;
if (a[i] !== b[i]) {
return false;
}
}
return true;
}

View file

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

View file

@ -1,4 +1,5 @@
define(['browser'], function (browser) {
'use strict';
function canPlayH264() {
var v = document.createElement('video');
@ -46,7 +47,7 @@ define(['browser'], function (browser) {
}
function canPlayHlsWithMSE() {
if (window.MediaSource != null && !browser.firefox) {
if (window.MediaSource != null) {
// text tracks dont work with this in firefox
return true;
}
@ -58,7 +59,7 @@ define(['browser'], function (browser) {
var typeString;
if (format == 'flac') {
if (format === 'flac') {
if (browser.tizen) {
return true;
}
@ -67,7 +68,7 @@ define(['browser'], function (browser) {
}
}
else if (format == 'wma') {
else if (format === 'wma') {
if (browser.tizen) {
return true;
}
@ -76,7 +77,7 @@ define(['browser'], function (browser) {
}
}
else if (format == 'opus') {
else if (format === 'opus') {
typeString = 'audio/ogg; codecs="opus"';
if (document.createElement('audio').canPlayType(typeString).replace(/no/, '')) {
@ -86,7 +87,7 @@ define(['browser'], function (browser) {
return false;
}
if (format == 'webma') {
if (format === 'webma') {
typeString = 'audio/webm';
} else {
typeString = 'audio/' + format;
@ -117,7 +118,7 @@ define(['browser'], function (browser) {
}
// 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;
}
@ -138,13 +139,14 @@ define(['browser'], function (browser) {
function testCanPlayTs() {
return browser.tizen || browser.web0s;
return browser.tizen || browser.web0s || browser.edgeUwp;
}
function getDirectPlayProfileForVideoContainer(container, videoAudioCodecs) {
var supported = false;
var profileContainer = container;
var videoCodecs = [];
switch (container) {
@ -153,7 +155,7 @@ define(['browser'], function (browser) {
videoAudioCodecs = [];
break;
case 'avi':
supported = browser.edgeUwp;
supported = browser.tizen || browser.edgeUwp;
break;
case 'mpg':
case 'mpeg':
@ -169,16 +171,19 @@ define(['browser'], function (browser) {
break;
case 'mov':
supported = browser.chrome || browser.edgeUwp;
videoCodecs.push('h264');
break;
case 'm2ts':
supported = browser.tizen || browser.web0s || browser.edgeUwp;
videoCodecs.push('h264');
break;
case 'wmv':
supported = browser.tizen || browser.web0s || browser.edgeUwp;
videoAudioCodecs = [];
break;
case 'ts':
supported = browser.tizen || browser.web0s || browser.edgeUwp;
supported = testCanPlayTs();
videoCodecs.push('h264');
profileContainer = 'ts,mpegts';
break;
default:
@ -192,6 +197,7 @@ define(['browser'], function (browser) {
return {
Container: profileContainer,
Type: 'Video',
VideoCodec: videoCodecs.join(','),
AudioCodec: videoAudioCodecs.join(',')
};
}
@ -199,7 +205,7 @@ define(['browser'], function (browser) {
function getMaxBitrate() {
if (browser.edgeUwp) {
return 15000000;
return 30000000;
}
// 10mbps
@ -216,7 +222,7 @@ define(['browser'], function (browser) {
if (browser.tizen) {
// 2015 models
if (userAgent.indexOf('tizen 2.3') != -1) {
if (userAgent.indexOf('tizen 2.3') !== -1) {
return 20000000;
}
@ -239,7 +245,6 @@ define(['browser'], function (browser) {
var canPlayWebm = videoTestElement.canPlayType('video/webm').replace(/no/, '');
var canPlayMkv = testCanPlayMkv(videoTestElement);
var canPlayTs = testCanPlayTs();
var profile = {};
@ -269,19 +274,20 @@ define(['browser'], function (browser) {
}
var mp3Added = false;
if (canPlayMkv || canPlayTs) {
if (canPlayMkv) {
if (supportsMp3VideoAudio) {
mp3Added = true;
videoAudioCodecs.push('mp3');
hlsVideoAudioCodecs.push('mp3');
}
}
if (videoTestElement.canPlayType('video/mp4; codecs="avc1.640029, mp4a.40.2"').replace(/no/, '')) {
videoAudioCodecs.push('aac');
hlsVideoAudioCodecs.push('aac');
}
if (!mp3Added && supportsMp3VideoAudio) {
videoAudioCodecs.push('mp3');
if (supportsMp3VideoAudio) {
if (!mp3Added) {
videoAudioCodecs.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) {
profile.DirectPlayProfiles.push({
Container: audioFormat == 'webma' ? 'webma,webm' : audioFormat,
Container: audioFormat === 'webma' ? 'webma,webm' : audioFormat,
Type: 'Audio'
});
// aac also appears in the m4a container
if (audioFormat == 'aac') {
if (audioFormat === 'aac') {
profile.DirectPlayProfiles.push({
Container: 'm4a',
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
if (canPlayMkv && options.supportsCustomSeeking && !browser.tizen) {
if (canPlayMkv && options.supportsCustomSeeking && !browser.tizen && options.enableMkvProgressive !== false) {
profile.TranscodingProfiles.push({
Container: 'mkv',
Type: 'Video',
@ -400,28 +406,15 @@ define(['browser'], function (browser) {
});
}
if (canPlayTs && options.supportsCustomSeeking && !browser.tizen && !browser.web0s) {
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()) {
if (canPlayHls() && options.enableHls !== false) {
profile.TranscodingProfiles.push({
Container: 'ts',
Type: 'Video',
AudioCodec: hlsVideoAudioCodecs.join(','),
VideoCodec: 'h264',
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({
Type: 'Video',
Codec: 'vpx',

View file

@ -1,3 +1,12 @@
button::-moz-focus-inner {
padding: 0;
border: 0;
}
button {
-webkit-border-fit: border !important;
}
.card {
border: 0;
font-size: inherit !important;
@ -82,10 +91,14 @@
transform: scale(1.16, 1.16);
}
.cardBox-mobile {
margin: 1px;
}
@media all and (min-width: 600px) {
.cardBox-mobile {
margin: 3px;
margin: 2px;
}
}
@ -147,7 +160,7 @@
.cardImageContainer {
/* Should be 0 with visualCardBox, but not really noticeable */
border-radius: 2px;
border-radius: 1px;
}
}
@ -179,6 +192,8 @@
bottom: 0;
/* Needed in case this is a button */
display: block;
/* Needed in safari */
height: 100%;
}
.cardImage {
@ -192,6 +207,23 @@
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 {
background-size: 100% 100%;
background-position: center center;
@ -211,12 +243,8 @@
}
.visualCardBox-cardFooter {
border-bottom-left-radius: 2px;
border-bottom-right-radius: 2px;
-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);
border-bottom-left-radius: 1px;
border-bottom-right-radius: 1px;
}
.innerCardFooter {
@ -245,6 +273,11 @@
overflow: hidden;
text-overflow: ellipsis;
color: inherit;
text-align: left;
}
.singleCardText {
padding: .5em;
}
.cardTextCentered {
@ -259,8 +292,9 @@
margin-right: 2em;
}
.cardCenteredText {
.cardDefaultText {
white-space: normal;
text-align: center;
}
.textActionButton {
@ -315,15 +349,21 @@
.cardOverlayButton {
color: #fff !important;
background-color: rgba(0,0,0,.7) !important;
background-color: rgba(0,0,0,.8) !important;
border-radius: 500px;
position: absolute;
bottom: 0;
right: 0;
margin: 0 .35em .5em 0;
z-index: 1;
/*opacity: 0;
transition: opacity 0.5s ease-in; /* vendorless fallback */ */;
}
/*.card:hover .cardOverlayButton {
opacity: 1;
}*/
.cardOverlayButton:hover {
background-color: rgba(0,0,0,.9) !important;
transition: background-color .5s ease-out;
@ -375,7 +415,7 @@
}
.overflowBackdropCard-scalable {
width: 84%;
width: 80%;
max-width: 400px;
}
@ -514,7 +554,6 @@
}
}
@media all and (min-width: 1600px) {
.portraitCard-scalable {
@ -524,12 +563,27 @@
.smallBackdropCard-scalable {
width: 12.5%;
}
.backdropCard-scalable {
width: 20%;
}
.squareCard-scalable {
width: 12.5%;
}
}
@media all and (min-width: 1800px) {
.smallBackdropCard-scalable {
width: 10%;
}
}
@media all and (min-width: 1920px) {
.squareCard-scalable {
width: 12.5%;
width: 11.111111111111111111111111111111%;
}
.smallBackdropCard-scalable {
@ -539,10 +593,6 @@
@media all and (min-width: 2100px) {
.squareCard-scalable {
width: 11.111111111111111111111111111111%;
}
.backdropCard-scalable {
width: 20%;
}
@ -582,6 +632,10 @@
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) {
'use strict';
function buildChapterCardsHtml(item, chapters, options) {
@ -6,7 +7,7 @@ define(['datetime', 'imageLoader', 'connectionManager', 'layoutManager'], functi
var mediaStreams = ((item.MediaSources || [])[0] || {}).MediaStreams || [];
var videoStream = mediaStreams.filter(function (i) {
return i.Type == 'Video';
return i.Type === 'Video';
})[0] || {};
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++) {
if (options.rows && itemsInRow == 0) {
if (options.rows && itemsInRow === 0) {
html += '<div class="cardColumn">';
}
@ -91,22 +92,7 @@ define(['datetime', 'imageLoader', 'connectionManager', 'layoutManager'], functi
cardBoxCssClass += ' cardBox-focustransform';
}
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>'
;
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>';
return html;
}

View file

@ -1,133 +1,17 @@
define(['imageLoader', 'itemShortcuts', 'connectionManager', 'layoutManager'], function (imageLoader, itemShortcuts, connectionManager, layoutManager) {
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;
}
define(['cardBuilder'], function (cardBuilder) {
'use strict';
function buildPeopleCards(items, options) {
if (options.parentContainer) {
// Abort if the container has been disposed
if (!document.body.contains(options.parentContainer)) {
return;
}
if (items.length) {
options.parentContainer.classList.remove('hide');
} else {
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);
options = Object.assign(options || {}, {
cardLayout: true,
centerText: true,
showTitle: true,
cardFooterAside: 'none',
showPersonRoleOrType: true,
cardCssClass: 'personCard'
});
cardBuilder.buildCards(items, options);
}
return {

View file

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

View file

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

View file

@ -1,4 +1,5 @@
define(['globalize'], function (globalize) {
'use strict';
function parseISO8601Date(s, toLocal) {
@ -40,12 +41,12 @@
}
// if there's a timezone, calculate it
if (d[8] != "Z" && d[10]) {
if (d[8] !== "Z" && d[10]) {
var offset = d[10] * 60 * 60 * 1000;
if (d[11]) {
offset += d[11] * 60 * 1000;
}
if (d[9] == "-") {
if (d[9] === "-") {
ms -= offset;
} else {
ms += offset;
@ -103,60 +104,36 @@
return false;
}();
function toLocaleString(date) {
var currentLocale = globalize.getCurrentLocale();
function getCurrentLocale() {
var locale = globalize.getCurrentLocale();
return locale;
}
function toLocaleString(date, options) {
var currentLocale = getCurrentLocale();
return currentLocale && toLocaleTimeStringSupportsLocales ?
date.toLocaleString(currentLocale) :
date.toLocaleString(currentLocale, options || {}) :
date.toLocaleString();
}
function getLocaleDateStringParts(date) {
function toLocaleDateString(date, options) {
var day = getDayName(date);
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();
var currentLocale = getCurrentLocale();
return currentLocale && toLocaleTimeStringSupportsLocales ?
date.toLocaleDateString(currentLocale) :
date.toLocaleDateString(currentLocale, options || {}) :
date.toLocaleDateString();
}
function toLocaleTimeString(date) {
function toLocaleTimeString(date, options) {
var currentLocale = globalize.getCurrentLocale();
var currentLocale = getCurrentLocale();
return currentLocale && toLocaleTimeStringSupportsLocales ?
date.toLocaleTimeString(currentLocale) :
date.toLocaleTimeString();
date.toLocaleTimeString(currentLocale, options || {}).toLowerCase() :
date.toLocaleTimeString().toLowerCase();
}
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) {
@ -209,7 +162,7 @@
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 {
@ -218,7 +171,6 @@
toLocaleDateString: toLocaleDateString,
toLocaleString: toLocaleString,
getDisplayTime: getDisplayTime,
isRelativeDay: isRelativeDay,
getLocaleDateStringParts: getLocaleDateStringParts
isRelativeDay: isRelativeDay
};
});

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) {
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);
});
});
}
'use strict';
function showDialog(options, template) {
@ -23,10 +8,10 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
scrollY: false
};
if (layoutManager.tv) {
var enableTvLayout = layoutManager.tv;
if (enableTvLayout) {
dialogOptions.size = 'fullscreen';
} else {
//dialogOptions.size = 'mini';
}
var dlg = dialogHelper.createDialog(dialogOptions);
@ -35,17 +20,29 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
dlg.innerHTML = globalize.translateHtml(template, 'sharedcomponents');
if (layoutManager.tv) {
scrollHelper.centerFocus.on(dlg.querySelector('.formDialogContent'), false);
dlg.style['align-items'] = 'center';
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 {
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) {
// 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 || '';
@ -54,9 +51,9 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
for (i = 0, length = options.buttons.length; i < length; 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) {
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>';
}
dlg.style.minWidth = (Math.min(options.buttons.length * 150, dom.getWindowSize().innerWidth - 50)) + 'px';
dlg.querySelector('.formDialogFooter').innerHTML = html;
var dialogResult;
@ -82,7 +77,7 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
return dialogHelper.open(dlg).then(function () {
if (layoutManager.tv) {
if (enableTvLayout) {
scrollHelper.centerFocus.off(dlg.querySelector('.formDialogContent'), false);
}
@ -106,10 +101,6 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
options = text;
}
if (layoutManager.tv) {
return showTvDialog(options);
}
return new Promise(function (resolve, reject) {
require(['text!./dialog.template.html'], function (template) {
showDialog(options, template).then(resolve, reject);

View file

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

View file

@ -13,14 +13,14 @@
.dialog {
margin: 0;
border-radius: 1px;
border-radius: 4px;
-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;
padding: 0;
will-change: transform;
/* Strict does not work well with actionsheet */
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 {
@ -37,16 +37,19 @@
left: 0;
right: 0;
margin: 0;
box-shadow: none;
}
@media all and (max-width: 1280px), all and (max-height: 720px) {
.dialog-fixedSize {
.dialog-fixedSize, .dialog-fullscreen-lowres {
position: fixed !important;
top: 0 !important;
bottom: 0 !important;
left: 0 !important;
right: 0 !important;
margin: 0 !important;
box-shadow: none;
}
}
@ -92,5 +95,5 @@
}
.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) {
'use strict';
var globalOnOpenCallback;
@ -27,7 +28,7 @@
}
}
function dialogHashHandler(dlg, hash, resolve) {
function DialogHashHandler(dlg, hash, resolve) {
var self = this;
self.originalUrl = window.location.href;
@ -36,7 +37,7 @@
function onHashChange(e) {
var isBack = self.originalUrl == window.location.href;
var isBack = self.originalUrl === window.location.href;
if (isBack || !isOpened(dlg)) {
window.removeEventListener('popstate', onHashChange);
@ -50,10 +51,11 @@
function onBackCommand(e) {
if (e.detail.command == 'back') {
if (e.detail.command === 'back') {
self.closedByBack = true;
closeDialog(dlg);
e.preventDefault();
e.stopPropagation();
closeDialog(dlg);
}
}
@ -74,7 +76,7 @@
if (!self.closedByBack && isHistoryEnabled(dlg)) {
var state = history.state || {};
if (state.dialogId == hash) {
if (state.dialogId === hash) {
history.back();
}
}
@ -83,7 +85,7 @@
activeElement.focus();
}
if (dlg.getAttribute('data-removeonclose') != 'false') {
if (dlg.getAttribute('data-removeonclose') !== 'false') {
removeCenterFocus(dlg);
var dialogContainer = dlg.dialogContainer;
@ -117,8 +119,12 @@
addBackdropOverlay(dlg);
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');
removeScrollLockOnClose = true;
}
@ -126,7 +132,7 @@
animateDialogOpen(dlg);
if (isHistoryEnabled(dlg)) {
historyManager.pushState({ dialogId: hash }, "Dialog", hash);
historyManager.pushState({ dialogId: hash }, "Dialog", '#' + hash);
window.addEventListener('popstate', onHashChange);
} else {
@ -149,7 +155,7 @@
}, 0);
dom.addEventListener((dlg.dialogContainer || backdrop), 'click', function (e) {
if (e.target == dlg.dialogContainer) {
if (e.target === dlg.dialogContainer) {
close(dlg);
}
}, {
@ -158,7 +164,7 @@
}
function isHistoryEnabled(dlg) {
return dlg.getAttribute('data-history') == 'true';
return dlg.getAttribute('data-history') === 'true';
}
function open(dlg) {
@ -180,7 +186,7 @@
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: 'none', offset: 1 }];
var timing = elem.animationConfig.entry.timing;
return elem.animate(keyframes, timing).onfinish = onFinish;
elem.animate(keyframes, timing).onfinish = onFinish;
}
function slideUp(elem, onFinish) {
@ -216,7 +222,7 @@
{ transform: 'translate3d(0,30%,0)', opacity: 0, offset: 0 },
{ transform: 'none', opacity: 1, offset: 1 }];
var timing = elem.animationConfig.entry.timing;
return elem.animate(keyframes, timing).onfinish = onFinish;
elem.animate(keyframes, timing).onfinish = onFinish;
}
function fadeIn(elem, onFinish) {
@ -225,7 +231,7 @@
{ opacity: '0', offset: 0 },
{ opacity: '1', offset: 1 }];
var timing = elem.animationConfig.entry.timing;
return elem.animate(keyframes, timing).onfinish = onFinish;
elem.animate(keyframes, timing).onfinish = onFinish;
}
function scaleDown(elem) {
@ -277,18 +283,18 @@
}));
}
};
if (!dlg.animationConfig || !dlg.animate) {
if (!dlg.animationConfig) {
onAnimationFinish();
return;
}
var animation;
if (dlg.animationConfig.exit.name == 'fadeout') {
if (dlg.animationConfig.exit.name === 'fadeout') {
animation = fadeOut(dlg);
} else if (dlg.animationConfig.exit.name == 'scaledown') {
} else if (dlg.animationConfig.exit.name === 'scaledown') {
animation = scaleDown(dlg);
} else if (dlg.animationConfig.exit.name == 'slidedown') {
} else if (dlg.animationConfig.exit.name === 'slidedown') {
animation = slideDown(dlg);
} else {
onAnimationFinish();
@ -303,20 +309,20 @@
var onAnimationFinish = function () {
focusManager.pushScope(dlg);
if (dlg.getAttribute('data-autofocus') == 'true') {
if (dlg.getAttribute('data-autofocus') === 'true') {
focusManager.autoFocus(dlg);
}
};
if (!dlg.animationConfig || !dlg.animate) {
if (!dlg.animationConfig) {
onAnimationFinish();
return;
}
if (dlg.animationConfig.entry.name == 'fadein') {
if (dlg.animationConfig.entry.name === 'fadein') {
fadeIn(dlg, onAnimationFinish);
} else if (dlg.animationConfig.entry.name == 'scaleup') {
} else if (dlg.animationConfig.entry.name === 'scaleup') {
scaleUp(dlg, onAnimationFinish);
} else if (dlg.animationConfig.entry.name == 'slideup') {
} else if (dlg.animationConfig.entry.name === 'slideup') {
slideUp(dlg, onAnimationFinish);
}
}
@ -327,7 +333,7 @@
return options.lockScroll;
}
if (options.size == 'fullscreen') {
if (options.size === 'fullscreen') {
return true;
}

View file

@ -1,8 +1,9 @@
define([], function () {
'use strict';
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;
if (!elem || !elem.getAttribute) {
@ -20,7 +21,7 @@ define([], function () {
tagNames = [tagNames];
}
while (tagNames.indexOf(elem.tagName || '') == -1) {
while (tagNames.indexOf(elem.tagName || '') === -1) {
elem = elem.parentNode;
if (!elem) {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,4 +1,5 @@
define(['layoutManager', 'browser', 'dom', 'css!./emby-input', 'registerElement'], function (layoutManager, browser, dom) {
'use strict';
var EmbyInputPrototype = Object.create(HTMLInputElement.prototype);
@ -19,7 +20,7 @@
bubbles: false,
cancelable: false
}));
}
};
Object.defineProperty(HTMLInputElement.prototype, 'value', descriptor);
supportsFloatingLabel = true;
@ -86,7 +87,7 @@
label.classList.remove('inputLabel-float');
} else {
var instanceSupportsFloat = supportsFloatingLabel && this.type != 'date' && this.type != 'time';
var instanceSupportsFloat = supportsFloatingLabel && this.type !== 'date' && this.type !== 'time';
if (instanceSupportsFloat) {
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 () {
this.addEventListener('click', onClick);
@ -190,7 +241,9 @@
if (browser.touch) {
this.addEventListener('contextmenu', disableEvent);
} else {
this.addEventListener('contextmenu', onContextMenu);
if (this.getAttribute('data-contextmenu') !== 'false') {
this.addEventListener('contextmenu', onContextMenu);
}
}
if (layoutManager.desktop) {
@ -203,9 +256,11 @@
itemShortcuts.on(this, getShortcutOptions());
var userDataHandler = onUserDataChanged.bind(this);
events.on(serverNotifications, 'UserDataChanged', userDataHandler);
this.userDataHandler = userDataHandler;
addNotificationEvent(this, 'UserDataChanged', onUserDataChanged);
addNotificationEvent(this, 'TimerCreated', onTimerCreated);
addNotificationEvent(this, 'SeriesTimerCreated', onSeriesTimerCreated);
addNotificationEvent(this, 'TimerCancelled', onTimerCancelled);
addNotificationEvent(this, 'SeriesTimerCancelled', onSeriesTimerCancelled);
};
ItemsContainerProtoType.detachedCallback = function () {
@ -218,11 +273,11 @@
this.removeEventListener('contextmenu', disableEvent);
itemShortcuts.off(this, getShortcutOptions());
var userDataHandler = this.userDataHandler;
if (userDataHandler) {
events.off(serverNotifications, 'UserDataChanged', userDataHandler);
this.userDataHandler = null;
}
removeNotificationEvent(this, 'UserDataChanged');
removeNotificationEvent(this, 'TimerCreated');
removeNotificationEvent(this, 'SeriesTimerCreated');
removeNotificationEvent(this, 'TimerCancelled');
removeNotificationEvent(this, 'SeriesTimerCancelled');
};
document.registerElement('emby-itemscontainer', {

View file

@ -21,8 +21,9 @@
.mdl-radio__button {
line-height: 24px;
position: absolute;
width: 0;
height: 0;
/* 1px is for focusing purposes, so the focusManager doesn't skip over it */
width: 1px;
height: 1px;
margin: 0;
padding: 0;
opacity: 0;
@ -43,13 +44,13 @@
height: 16px;
margin: 0;
cursor: pointer;
border: 2px solid rgba(0,0,0, 0.54);
border: 2px solid currentcolor;
border-radius: 50%;
z-index: 2;
}
.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 {
@ -75,7 +76,7 @@
-webkit-transform: scale3d(0, 0, 0);
transform: scale3d(0, 0, 0);
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 {
@ -89,7 +90,11 @@
}
.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 {

View file

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

View file

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

View file

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

View file

@ -1,4 +1,5 @@
define(['browser', 'css!./emby-slider', 'registerElement', 'emby-input'], function (browser) {
'use strict';
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) + '%';
if (range.getBubbleText) {
@ -41,7 +41,7 @@
EmbySliderPrototype.attachedCallback = function () {
if (this.getAttribute('data-embycheckbox') == 'true') {
if (this.getAttribute('data-embycheckbox') === 'true') {
return;
}
@ -71,16 +71,26 @@
this.addEventListener('input', function (e) {
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) {
sliderBubble.classList.remove('hide');
hasHideClass = false;
}
});
this.addEventListener('change', function () {
this.dragging = false;
updateValues(this, backgroundLower, backgroundUpper);
this.addEventListener('mouseleave', function () {
sliderBubble.classList.add('hide');
hasHideClass = true;
});

View file

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

View file

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

View file

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

View file

@ -1,4 +1,5 @@
define(['layoutManager', 'browser', 'css!./emby-textarea', 'registerElement'], function (layoutManager, browser) {
'use strict';
function autoGrow(textarea, maxLines) {
var self = this;
@ -84,7 +85,7 @@
bubbles: false,
cancelable: false
}));
}
};
Object.defineProperty(HTMLTextAreaElement.prototype, 'value', descriptor);
supportsFloatingLabel = true;
@ -113,7 +114,7 @@
label.innerHTML = this.getAttribute('label') || '';
label.classList.add('textareaLabel');
if (!supportsFloatingLabel || this.type == 'date') {
if (!supportsFloatingLabel || this.type === 'date') {
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 () {
'use strict';
function getFetchPromise(request) {
var headers = request.headers || {};
if (request.dataType == 'json') {
if (request.dataType === 'json') {
headers.accept = 'application/json';
}
@ -107,9 +108,9 @@
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();
} 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();
} else {
return response;

View file

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

View file

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

View file

@ -1,4 +1,5 @@
define(['connectionManager', 'userSettings', 'events'], function (connectionManager, userSettings, events) {
'use strict';
var allTranslations = {};
var currentCulture;
@ -69,20 +70,20 @@ define(['connectionManager', 'userSettings', 'events'], function (connectionMana
// If it's de-DE, convert to just de
var parts = culture.split('-');
if (parts.length == 2) {
if (parts[0].toLowerCase() == parts[1].toLowerCase()) {
if (parts.length === 2) {
if (parts[0].toLowerCase() === parts[1].toLowerCase()) {
culture = parts[0].toLowerCase();
}
}
var lower = culture.toLowerCase();
if (lower == 'ca-es') {
if (lower === 'ca-es') {
return 'ca';
}
// normalize Swedish
if (lower == 'sv-se') {
if (lower === 'sv-se') {
return 'sv';
}
@ -130,12 +131,12 @@ define(['connectionManager', 'userSettings', 'events'], function (connectionMana
lang = normalizeLocaleName(lang);
var filtered = translations.filter(function (t) {
return normalizeLocaleName(t.lang) == lang;
return normalizeLocaleName(t.lang) === lang;
});
if (!filtered.length) {
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;
url += url.indexOf('?') == -1 ? '?' : '&';
url += url.indexOf('?') === -1 ? '?' : '&';
url += 'v=' + cacheParam;
var xhr = new XMLHttpRequest();
@ -217,14 +218,14 @@ define(['connectionManager', 'userSettings', 'events'], function (connectionMana
var startIndex = html.indexOf('${');
if (startIndex == -1) {
if (startIndex === -1) {
return html;
}
startIndex += 2;
var endIndex = html.indexOf('}', startIndex);
if (endIndex == -1) {
if (endIndex === -1) {
return html;
}
@ -250,7 +251,7 @@ define(['connectionManager', 'userSettings', 'events'], function (connectionMana
events.on(connectionManager, 'localusersignedin', updateCurrentCulture);
events.on(userSettings, 'change', function (e, name) {
if (name == 'language') {
if (name === 'language') {
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) {
var i, length;
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');
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) {
var i, length;
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');
if (chkIndicators[i].getAttribute('data-default') == 'true') {
chkIndicators[i].checked = userSettings.get('guide-indicator-' + type) != 'false';
if (chkIndicators[i].getAttribute('data-default') === 'true') {
chkIndicators[i].checked = userSettings.get('guide-indicator-' + type) !== 'false';
} 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">
<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>
<div class="checkboxList">
<label>
@ -30,5 +38,10 @@
<span>${RepeatEpisodes}</span>
</label>
</div>
<br />
<label class="checkboxContainer">
<input type="checkbox" is="emby-checkbox" class="chkColorCodedBackgrounds" />
<span>${EnableColorCodedBackgrounds}</span>
</label>
</form>
</div>

View file

@ -8,6 +8,8 @@
white-space: nowrap;
width: 100%;
flex-shrink: 0;
display: flex;
padding-left: 3.4em;
}
.tvProgramSectionHeader {
@ -21,34 +23,10 @@
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 {
text-transform: uppercase;
border-radius: 2px;
margin-right: .5em;
color: #fff;
font-size: 74%;
padding: .2em .25em;
display: inline-flex;
@ -58,48 +36,8 @@
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 {
float: left;
flex-shrink: 0;
}
.timeslotHeaders {
@ -109,15 +47,14 @@
.programContainer {
white-space: nowrap;
position: relative;
}
.programGridContainer {
margin-left: 12.2vw;
display: flex;
align-items: flex-start;
}
.channelPrograms {
white-space: nowrap;
position: relative;
contain: strict;
}
.timeslotHeadersInner {
@ -200,7 +137,6 @@
background: rgba(40, 40, 40, .9);
display: flex;
align-items: center;
color: #fff !important;
text-decoration: none;
/* Needed in firefox */
text-align: left;
@ -281,7 +217,7 @@
.channelHeaderCell {
border-bottom: .65vh solid #121212 !important;
background-size: auto 70%;
background-position: 90% center;
background-position: 92% center;
background-repeat: no-repeat;
}
@ -301,6 +237,12 @@
.channelPrograms, .channelHeaderCell {
height: 4em;
contain: strict;
}
.channelPrograms {
display: flex;
flex-direction: column;
}
.channelPrograms-tv, .channelHeaderCell-tv {
@ -319,14 +261,6 @@
height: 3em;
}
.pointerInput .channelHeaderCell:hover {
background-color: #444;
}
.channelList {
float: left;
}
.programGrid {
padding-bottom: 4px;
}
@ -343,7 +277,6 @@
border-left: .65vh solid #121212 !important;
background-color: rgba(32, 32, 32, .95);
display: flex;
color: #fff !important;
text-decoration: none;
overflow: hidden;
align-items: center;
@ -352,15 +285,32 @@
contain: strict;
}
.timeslotCellInner {
.programAccent {
position: absolute;
bottom: 0;
overflow: hidden;
width: 100%;
top: 0;
display: block;
text-decoration: none;
color: #fff !important;
left: 0;
right: 0;
height: 2px;
}
.sportsAccent {
background-color: #3949AB;
}
.movieAccent {
background-color: #5E35B1;
}
.childAccent {
background-color: #039BE5;
}
.newsAccent {
background-color: #43A047;
}
.specialsAccent {
background-color: #FB8C00;
}
.guideProgramName {
@ -371,11 +321,6 @@
align-items: center;
}
.guideProgramTime {
padding: 0 .5em .35em;
color: #bbb;
}
.programIcon {
margin-left: auto;
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 {
height: auto !important;
contain: layout style;
}
.programCell, .channelHeaderCell, .btnSelectDate {
@ -435,6 +413,11 @@
color: #cc3333 !important;
}
.seriesTimerIcon-inactive {
color: inherit !important;
opacity: .7;
}
.visibleGuideScroller::-webkit-scrollbar {
width: 10px;
height: 10px;
@ -460,3 +443,14 @@
display: flex;
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) {
@ -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) {
var self = this;
var items = {};
self.options = options;
self.categoryOptions = { categories: [] };
// 30 mins
var cellCurationMinutes = 30;
@ -26,14 +39,6 @@
var currentStartIndex = 0;
var currentChannelLimit = 0;
var channelQuery = {
StartIndex: 0,
EnableFavoriteSorting: true
};
var channelsPromise;
self.refresh = function () {
currentDate = null;
@ -151,6 +156,12 @@
var apiClient = connectionManager.currentApiClient();
var channelQuery = {
StartIndex: 0,
EnableFavoriteSorting: userSettings.get('livetv-favoritechannelsattop') !== 'false'
};
channelQuery.UserId = apiClient.getCurrentUserId();
getChannelLimit(context).then(function (channelLimit) {
@ -165,7 +176,44 @@
channelQuery.EnableUserData = false;
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;
// Add one second to avoid getting programs that are just ending
@ -175,7 +223,7 @@
var nextDay = new Date(date.getTime() + msPerDay - 2000);
console.log(nextDay);
channelsPromise.then(function (channelsResult) {
apiClient.getLiveTvChannels(channelQuery).then(function (channelsResult) {
var btnPreviousPage = context.querySelector('.btnPreviousPage');
var btnNextPage = context.querySelector('.btnNextPage');
@ -299,6 +347,37 @@
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) {
var html = '';
@ -307,18 +386,28 @@
var endMs = startMs + msPerDay - 1;
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++) {
var program = programs[i];
if (program.ChannelId != channel.Id) {
if (program.ChannelId !== channel.Id) {
continue;
}
@ -344,20 +433,45 @@
endPercent *= 100;
var cssClass = "programCell clearButton itemAction";
var addAccent = true;
var accentCssClass = null;
var displayInnerContent = true;
if (program.IsKids) {
cssClass += " childProgramInfo";
displayInnerContent = displayKidsContent;
accentCssClass = 'childAccent';
} else if (program.IsSports) {
cssClass += " sportsProgramInfo";
displayInnerContent = displaySportsContent;
accentCssClass = 'sportsAccent';
} else if (program.IsNews) {
cssClass += " newsProgramInfo";
displayInnerContent = displayNewsContent;
accentCssClass = 'newsAccent';
} else if (program.IsMovie) {
cssClass += " movieProgramInfo";
displayInnerContent = displayMovieContent;
accentCssClass = 'movieAccent';
}
else if (program.IsSeries) {
cssClass += " plainProgramInfo";
displayInnerContent = displaySeriesContent;
}
else {
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 = '';
@ -367,49 +481,38 @@
if (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 += '<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 += '<div class="' + guideProgramNameClass + '">';
html += program.Name;
html += '</div>';
if (program.IsLive && options.showLiveIndicator) {
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 += '<i class="guideHdIcon md-icon programIcon">hd</i>';
}
html += program.Name;
html += '</div>';
if (program.SeriesTimerId) {
html += '<i class="seriesTimerIcon md-icon programIcon">fiber_smart_record</i>';
}
else if (program.TimerId) {
html += '<i class="timerIcon md-icon programIcon">fiber_manual_record</i>';
}
if (program.IsHD && options.showHdIcon) {
html += '<i class="guideHdIcon md-icon programIcon">hd</i>';
}
if (addAccent) {
html += getTimerIndicator(program);
if (program.IsKids) {
html += '<div class="programAccent childAccent"></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>';
if (accentCssClass) {
html += '<div class="programAccent ' + accentCssClass + '"></div>';
}
}
@ -431,11 +534,11 @@
var allowIndicators = dom.getWindowSize().innerWidth >= 600;
var options = {
showHdIcon: allowIndicators && userSettings.get('guide-indicator-hd') == 'true',
showLiveIndicator: allowIndicators && userSettings.get('guide-indicator-live') != 'false',
showPremiereIndicator: allowIndicators && userSettings.get('guide-indicator-premiere') != 'false',
showNewIndicator: allowIndicators && userSettings.get('guide-indicator-new') == 'true',
showRepeatIndicator: allowIndicators && userSettings.get('guide-indicator-repeat') == 'true'
showHdIcon: allowIndicators && userSettings.get('guide-indicator-hd') === 'true',
showLiveIndicator: allowIndicators && userSettings.get('guide-indicator-live') !== 'false',
showPremiereIndicator: allowIndicators && userSettings.get('guide-indicator-premiere') !== 'false',
showNewIndicator: allowIndicators && userSettings.get('guide-indicator-new') === 'true',
showRepeatIndicator: allowIndicators && userSettings.get('guide-indicator-repeat') === 'true'
};
for (var i = 0, length = channels.length; i < length; i++) {
@ -497,19 +600,6 @@
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) {
//var list = [];
@ -555,7 +645,7 @@
var channelRowId = null;
if (activeElement) {
channelRowId = parentWithClass(activeElement, 'channelPrograms');
channelRowId = dom.parentWithClass(activeElement, 'channelPrograms');
channelRowId = channelRowId && channelRowId.getAttribute ? channelRowId.getAttribute('data-channelid') : null;
}
@ -572,7 +662,7 @@
var focusElem;
if (itemId) {
focusElem = context.querySelector('[data-id="' + itemId + '"]')
focusElem = context.querySelector('[data-id="' + itemId + '"]');
}
if (focusElem) {
@ -582,7 +672,7 @@
var autoFocusParent;
if (channelRowId) {
autoFocusParent = context.querySelector('[data-channelid="' + channelRowId + '"]')
autoFocusParent = context.querySelector('[data-channelid="' + channelRowId + '"]');
}
if (!autoFocusParent) {
@ -637,13 +727,8 @@
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;
}
@ -671,7 +756,7 @@
while (start <= end) {
dateOptions.push({
name: datetime.getLocaleDateStringParts(start).join(' '),
name: datetime.toLocaleDateString(start, { weekday: 'long', month: 'long', day: 'numeric' }),
id: start.getTime()
});
@ -704,7 +789,7 @@
var selectedDate = currentDate || new Date();
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) {
@ -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) {
var programCell = parentWithClass(e.target, 'programCell');
var programCell = dom.parentWithClass(e.target, 'programCell');
if (!programCell) {
return;
@ -781,7 +853,7 @@
var icon = cell.querySelector('.timerIcon');
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) {
@ -855,19 +927,16 @@
context.querySelector('.btnUnlockGuide').addEventListener('click', function () {
currentStartIndex = 0;
channelsPromise = null;
reloadPage(context);
});
context.querySelector('.btnNextPage').addEventListener('click', function () {
currentStartIndex += currentChannelLimit;
channelsPromise = null;
reloadPage(context);
});
context.querySelector('.btnPreviousPage').addEventListener('click', function () {
currentStartIndex = Math.max(currentStartIndex - currentChannelLimit, 0);
channelsPromise = null;
reloadPage(context);
});
@ -875,6 +944,10 @@
showViewSettings(self);
});
context.querySelector('.btnCategories').addEventListener('click', function () {
showCategoryOptions(self);
});
context.classList.add('tvguide');
setScrollEvents(context, true);
@ -889,7 +962,7 @@
self.refresh();
});
};
}
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="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="guideDateText">
</div>
@ -14,10 +14,19 @@
<div class="timeslotHeaders smoothScrollX guideScroller" style="scroll-behavior: auto;"></div>
</div>
<div class="smoothScrollY guideVerticalScroller programContainer guideScroller" style="flex-grow: 1;">
<div class="channelList"></div>
<div style="display: flex;flex-grow:1;overflow:hidden;">
<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>

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) {
'use strict';
var currentItem;
var hasChanges = false;
@ -78,11 +79,11 @@
options.type = type;
options.index = index;
if (type == 'Backdrop') {
if (type === 'Backdrop') {
options.tag = item.BackdropImageTags[index];
} else if (type == 'Screenshot') {
} else if (type === 'Screenshot') {
options.tag = item.ScreenshotImageTags[index];
} else if (type == 'Primary') {
} else if (type === 'Primary') {
options.tag = item.PrimaryImageTag || item.ImageTags[type];
} else {
options.tag = item.ImageTags[type];
@ -101,7 +102,7 @@
cssClass += " backdropCard backdropCard-scalable";
if (tagName == 'button') {
if (tagName === 'button') {
cssClass += ' card-focusscale btnImageCard';
cardBoxCssClass += ' cardBox-focustransform cardBox-focustransform-transition';
@ -142,27 +143,27 @@
if (enableFooterButtons) {
html += '<div class="cardText cardTextCentered">';
if (image.ImageType == "Backdrop" || image.ImageType == "Screenshot") {
if (image.ImageType === "Backdrop" || image.ImageType === "Screenshot") {
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 {
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) {
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 {
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 {
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>';
}
@ -192,7 +193,13 @@
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;
reload(context, null, focusContext);
}, function() {
require(['alert'], function (alert) {
alert(globalize.translate('sharedcomponents#DefaultErrorMessage'));
});
});
}
@ -227,31 +239,12 @@
elem.innerHTML = html;
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) {
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'));
@ -260,7 +253,7 @@
function renderBackdrops(page, apiClient, item, imageInfos, imageProviders) {
var images = imageInfos.filter(function (i) {
return i.ImageType == "Backdrop";
return i.ImageType === "Backdrop";
}).sort(function (a, b) {
return a.ImageIndex - b.ImageIndex;
@ -277,7 +270,7 @@
function renderScreenshots(page, apiClient, item, imageInfos, imageProviders) {
var images = imageInfos.filter(function (i) {
return i.ImageType == "Screenshot";
return i.ImageType === "Screenshot";
}).sort(function (a, b) {
return a.ImageIndex - b.ImageIndex;
@ -299,6 +292,10 @@
hasChanges = true;
reload(page);
});
}, function () {
require(['alert'], function (alert) {
alert('This feature is coming soon to Emby Theater.');
});
});
}
@ -322,7 +319,7 @@
id: 'delete'
});
if (type == 'Backdrop' || type == 'Screenshot') {
if (type === 'Backdrop' || type === 'Screenshot') {
if (index > 0) {
commands.push({
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');
require(['components/imageuploader/imageuploader'], function (imageUploader) {
@ -390,18 +387,42 @@
if (hasChanged) {
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 () {
showImageDownloader(page, this.getAttribute('data-imagetype') || 'Primary');
addListeners(context, 'btnSearchImages', 'click', function () {
showImageDownloader(context, this.getAttribute('data-imagetype'));
});
addListeners(page, 'btnImageCard', 'click', function () {
showActionSheet(page, this);
addListeners(context, 'btnBrowseAllImages', 'click', function () {
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) {
if (elem.tagName !== "IMG") {
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 {

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 thresholdY;
var requestIdleCallback = window.requestIdleCallback || function (fn) {
fn();
};
//var imagesWorker = new Worker(require.toUrl('.').split('?')[0] + '/imagesworker.js');
var supportsIntersectionObserver = function () {
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;
}
@ -25,8 +26,8 @@ define(['visibleinviewport', 'imageFetcher', 'layoutManager', 'events', 'browser
var y = screen.availHeight;
if (browser.touch) {
x *= 2;
y *= 2;
x *= 1.5;
y *= 1.5;
}
thresholdX = x;
@ -53,14 +54,174 @@ define(['visibleinviewport', 'imageFetcher', 'layoutManager', 'events', 'browser
if (!source) {
source = elem.getAttribute('data-src');
}
if (source) {
if (enableFade && !layoutManager.tv && enableEffects !== false) {
imageFetcher.loadImage(elem, source).then(fadeIn);
} else {
imageFetcher.loadImage(elem, source);
}
elem.removeAttribute("data-src");
if (!source) {
return;
}
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) {
@ -231,31 +392,33 @@ define(['visibleinviewport', 'imageFetcher', 'layoutManager', 'events', 'browser
var result;
if (values.length % 2)
if (values.length % 2) {
result = values[half];
else
}
else {
result = (values[half - 1] + values[half]) / 2.0;
}
// If really close to 2:3 (poster image), just return 2:3
var aspect2x3 = 2 / 3;
if (Math.abs(aspect2x3 - result) <= .15) {
if (Math.abs(aspect2x3 - result) <= 0.15) {
return aspect2x3;
}
// If really close to 16:9 (episode image), just return 16:9
var aspect16x9 = 16 / 9;
if (Math.abs(aspect16x9 - result) <= .2) {
if (Math.abs(aspect16x9 - result) <= 0.2) {
return aspect16x9;
}
// 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;
}
// If really close to 4:3 (poster image), just return 2:3
var aspect4x3 = 4 / 3;
if (Math.abs(aspect4x3 - result) <= .15) {
if (Math.abs(aspect4x3 - result) <= 0.15) {
return aspect4x3;
}
@ -274,6 +437,7 @@ define(['visibleinviewport', 'imageFetcher', 'layoutManager', 'events', 'browser
self.lazyImage = fillImage;
self.lazyChildren = lazyChildren;
self.getPrimaryImageAspectRatio = getPrimaryImageAspectRatio;
self.getCachedVibrantInfo = getCachedVibrantInfo;
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 () {
'use strict';
function loadImage(elem, url) {
@ -20,7 +21,7 @@ define(['cryptojs-md5'], function () {
function createDir(rootDirEntry, folders, callback, errorCallback) {
// 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);
}
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
var index = url.indexOf('://');
if (index != -1) {
if (index !== -1) {
url = url.substring(index + 3);
index = url.indexOf('/');
if (index != -1) {
if (index !== -1) {
url = url.substring(index + 1);
}
@ -163,12 +164,12 @@ define(['cryptojs-md5'], function () {
xhr.responseType = "arraybuffer";
xhr.onload = function (e) {
if (this.status == 200) {
if (this.status === 200) {
writeData(dir, filename, this.getResponseHeader('Content-Type'), this.response, callback, errorCallback);
} else {
errorCallback();
}
}
};
xhr.send();
}
@ -200,7 +201,7 @@ define(['cryptojs-md5'], function () {
return new Promise(function (resolve, reject) {
if (originalUrl.indexOf('tag=') != -1) {
if (originalUrl.indexOf('tag=') !== -1) {
originalUrl += "&accept=webp";
}

View file

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

View file

@ -1,9 +1,10 @@
define(['css!./indicators.css', 'material-icons'], function () {
'use strict';
function enableProgressIndicator(item) {
if (item.MediaType == 'Video') {
if (item.Type != 'TvChannel') {
if (item.MediaType === 'Video') {
if (item.Type !== 'TvChannel') {
return true;
}
}
@ -27,7 +28,7 @@ define(['css!./indicators.css', 'material-icons'], function () {
function getProgressBarHtml(item, options) {
if (enableProgressIndicator(item)) {
if (item.Type == "Recording" && item.CompletionPercentage) {
if (item.Type === "Recording" && item.CompletionPercentage) {
return getProgressHtml(item.CompletionPercentage, options);
}
@ -48,9 +49,9 @@ define(['css!./indicators.css', 'material-icons'], function () {
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;
}
}
@ -98,19 +99,38 @@ define(['css!./indicators.css', 'material-icons'], function () {
function getTimerIndicator(item) {
if (item.SeriesTimerId) {
return '<i class="md-icon timerIndicator indicatorIcon">fiber_smart_record</i>';
var status;
if (item.Type === 'SeriesTimer') {
return '<i class="md-icon timerIndicator indicatorIcon">&#xE062;</i>';
}
if (item.TimerId) {
return '<i class="md-icon timerIndicator indicatorIcon">fiber_manual_record</i>';
else if (item.TimerId || item.SeriesTimerId) {
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) {
if (item.SyncPercent == 100) {
if (item.SyncPercent === 100) {
return '<div class="syncIndicator indicator fullSyncIndicator"><i class="md-icon indicatorIcon">file_download</i></div>';
} else if (item.SyncPercent != null) {
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':
playbackManager.toggleMute();
break;
case 'channelup':
playbackManager.nextTrack();
break;
case 'channeldown':
playbackManager.previousTrack();
break;
case 'volumedown':
playbackManager.volumeDown();
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({
name: globalize.translate('sharedcomponents#ButtonCancel'),
name: globalize.translate('sharedcomponents#CancelRecording'),
id: 'canceltimer'
});
}
if (item.CanDelete) {
if ((item.Type == 'Recording' && item.Status == 'InProgress') && user.Policy.EnableLiveTvManagement && options.cancelTimer !== false) {
commands.push({
name: globalize.translate('sharedcomponents#Delete'),
id: 'delete'
name: globalize.translate('sharedcomponents#CancelRecording'),
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({
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) {
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) {
commands.push({
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 (options.play !== false) {
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({
name: Globalize.translate('sharedcomponents#Record'),
@ -170,7 +183,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'embyRouter',
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({
name: globalize.translate('sharedcomponents#Refresh'),
id: 'refresh'
@ -383,7 +396,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'embyRouter',
}
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;
}
case 'share':
@ -480,6 +493,9 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'embyRouter',
case 'canceltimer':
deleteTimer(apiClient, item, resolve, id);
break;
case 'cancelseriestimer':
deleteSeriesTimer(apiClient, item, resolve, id);
break;
default:
reject();
break;
@ -489,21 +505,22 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'embyRouter',
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) {
toast(globalize.translate('sharedcomponents#RecordingCancelled'));
});
require(['recordingHelper'], function (recordingHelper) {
loading.hide();
getResolveFunction(resolve, command, true)();
});
recordingHelper.cancelSeriesTimerWithConfirmation(item.Id, item.ServerId).then(function () {
getResolveFunction(resolve, command, true)();
});
});
}
@ -539,6 +556,11 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'embyRouter',
if (item.Type == 'Timer') {
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);
});
} 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) {
var itemId = item.Id;
var msg = globalize.translate('sharedcomponents#ConfirmDeleteItem');
var title = globalize.translate('sharedcomponents#HeaderDeleteItem');
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 () {
resolve(true);
@ -585,6 +616,10 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'embyRouter',
return getCommands(options).then(function (commands) {
if (!commands.length) {
return Promise.reject();
}
return new Promise(function (resolve, reject) {
require(['actionsheet'], function (actionSheet) {

View file

@ -8,7 +8,11 @@ define(['apphost'], function (appHost) {
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") {
@ -37,7 +41,7 @@ define(['apphost'], function (appHost) {
number += "-" + displayIndexNumber;
}
name = number + " - " + name;
name = name ? (number + " - " + name) : number;
}
@ -46,26 +50,45 @@ define(['apphost'], function (appHost) {
function supportsAddingToCollection(item) {
if (item.Type == 'Timer') {
if (item.Type == 'Timer' || item.Type == 'SeriesTimer') {
return false;
}
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';
}
function supportsAddingToPlaylist(item) {
if (item.Type == 'Program') {
return false;
}
if (item.Type == 'Timer') {
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") {
return false;
@ -75,12 +98,13 @@ define(['apphost'], function (appHost) {
return false;
}
if (user.Policy.IsAdministrator) {
return true;
if (item.Type == 'Recording') {
if (item.Status != 'Completed') {
return false;
}
}
return false;
return user.Policy.IsAdministrator;
}
return {
@ -111,7 +135,9 @@ define(['apphost'], function (appHost) {
canEdit: canEdit,
canEditImages: function (user, itemType) {
canEditImages: function (user, item) {
var itemType = item.Type;
if (itemType == 'UserView') {
if (user.Policy.IsAdministrator) {
@ -122,7 +148,13 @@ define(['apphost'], function (appHost) {
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) {
@ -139,6 +171,14 @@ define(['apphost'], function (appHost) {
if (item.Type == 'Timer') {
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');
}
};

View file

@ -77,7 +77,7 @@
var isPortrait = className.indexOf('portrait') != -1;
var parentName = isSmallItem || isMiniItem || isPortrait ? null : item.SeriesName;
var name = itemHelper.getDisplayName(item);
var name = item.EpisodeTitle ? item.Name : itemHelper.getDisplayName(item);
html += '<div>';
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>';
buttonCount++;
html += userdataButtons.getIconsHtml({
item: item,
style: 'fab-mini',
cssClass: 'cardOverlayFab',
iconCssClass: 'cardOverlayFab-md-icon'
});
html += '</div>';
html += '</div>';
@ -198,7 +191,7 @@
var id = dataElement.getAttribute('data-id');
var type = dataElement.getAttribute('data-type');
if (type == 'Timer') {
if (type == 'Timer' || type == 'SeriesTimer') {
return;
}
@ -215,6 +208,16 @@
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);
});
@ -243,7 +246,7 @@
showOverlayTimeout = setTimeout(function () {
onShowTimerExpired(card);
}, 1000);
}, 1400);
}
function preventTouchHover() {

View file

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

View file

@ -15,19 +15,10 @@
overflow: hidden;
}
.listItem-border {
border-bottom: 1px solid #2a2a2a;
}
.listItem-button {
width: 100%;
}
.listItem-nosidepadding {
padding-left: 0;
padding-right: 0;
}
.listItem-largeImage {
padding: .5em !important;
}
@ -46,6 +37,7 @@
display: inline-block;
vertical-align: middle;
flex-shrink: 0;
contain: layout style;
}
.listViewDragHandle {
@ -54,33 +46,20 @@
.listItemBody {
flex-grow: 1;
padding: 0 1em;
padding: .8em 1em;
overflow: hidden;
text-overflow: ellipsis;
flex-direction: column;
vertical-align: middle;
justify-content: center;
min-height: 3.44em;
}
.listItemBody-nogrow {
flex-grow: initial;
flex-shrink: 0;
width: 9em;
opacity: .7;
.listItemBody-noleftpadding {
padding-left: 0;
}
@media all and (max-width: 800px) {
.listItemBody-nogrow {
width: 4em;
}
}
.two-line {
min-height: 5.15em;
padding-top: 0;
padding-bottom: 0;
.listItem-odd {
background: #1c1c1c;
}
.three-line {
@ -128,7 +107,6 @@
background-color: #52B54B;
padding: .5em;
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 {
@ -169,6 +147,7 @@
/* Don't display if flex not supported */
display: none;
align-items: center;
margin-right: 1em;
}
.listGroupHeader {
@ -191,6 +170,7 @@
.listItem, .listItemBody, .listItemMediaInfo {
display: flex;
contain: layout style;
}
}
@ -200,3 +180,7 @@
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++) {
var text = textlines[i];
if (!text) {
continue;
}
if (i === 0) {
if (isLargeStyle) {
html += '<h2 class="listItemBodyText">';
@ -143,7 +149,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
var clickEntireItem = layoutManager.tv ? true : false;
var outerTagName = clickEntireItem ? 'button' : 'div';
var enableSideMediaInfo = options.enableSideMediaInfo != null ? options.enableSideMediaInfo : clickEntireItem;
var enableSideMediaInfo = options.enableSideMediaInfo != null ? options.enableSideMediaInfo : true;
var outerHtml = '';
@ -178,10 +184,12 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
}
}
var cssClass = "listItem listItem-nosidepadding";
var cssClass = "listItem";
if (options.border !== false) {
cssClass += ' listItem-border';
if (options.highlight !== false) {
if (i % 2 == 1) {
cssClass += ' listItem-odd';
}
}
if (clickEntireItem) {
@ -242,23 +250,32 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
html += '</div>';
}
if (options.showProgramTimeColumn) {
html += '<div class="listItemBody listItemBody-nogrow listItemBody-rightborder"><div class="listItemBodyText">';
html += datetime.getDisplayTime(datetime.parseISO8601Date(item.StartDate));
html += ' - ';
html += datetime.getDisplayTime(datetime.parseISO8601Date(item.EndDate));
html += '</div></div>';
var textlines = [];
if (options.showProgramDateTime) {
textlines.push(datetime.toLocaleString(datetime.parseISO8601Date(item.StartDate), {
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 (item.Type == 'Episode') {
textlines.push(item.SeriesName || '&nbsp;');
parentTitle = item.SeriesName;
}
if (item.EpisodeTitle) {
textlines.push(item.Name || '&nbsp;');
else if (item.IsSeries) {
parentTitle = item.Name;
}
}
@ -267,21 +284,42 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
if (options.showIndexNumber && item.IndexNumber != null) {
displayName = item.IndexNumber + ". " + displayName;
}
textlines.push(displayName);
if (item.ArtistItems && item.Type != 'MusicAlbum') {
textlines.push(item.ArtistItems.map(function (a) {
return a.Name;
if (options.showParentTitle && options.parentTitleWithTitle) {
}).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') {
textlines.push(item.AlbumArtist || '&nbsp;');
if (displayName && !options.parentTitleWithTitle) {
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') {
textlines.push(item.GameSystem || '&nbsp;');
textlines.push(item.GameSystem);
}
if (item.Type == 'TvChannel') {
@ -291,24 +329,31 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
}
}
cssClass = 'listItemBody two-line';
cssClass = 'listItemBody';
if (!clickEntireItem) {
cssClass += ' itemAction';
}
if (options.image === false) {
cssClass += ' itemAction listItemBody-noleftpadding';
}
html += '<div class="' + cssClass + '">';
var moreIcon = appHost.moreIcon == 'dots-horiz' ? '&#xE5D3;' : '&#xE5D4;';
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, {
episodeTitle: false
}) + '</div>';
html += '<div class="' + mediaInfoClass + '">' + mediaInfo.getPrimaryMediaInfoHtml(item, {
episodeTitle: false,
originalAirDate: false
}) + '</div>';
}
}
if (enableOverview && item.Overview) {
@ -319,18 +364,32 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
html += '</div>';
if (enableSideMediaInfo) {
html += '<div class="secondary listItemMediaInfo">' + mediaInfo.getPrimaryMediaInfoHtml(item, {
if (options.mediaInfo !== false) {
if (enableSideMediaInfo) {
html += '<div class="secondary listItemMediaInfo">' + mediaInfo.getPrimaryMediaInfoHtml(item, {
year: false,
container: false,
episodeTitle: false
year: false,
container: false,
episodeTitle: false
}) + '</div>';
}) + '</div>';
}
}
if (!options.recordButton && (item.Type == 'Timer' || item.Type == 'Program')) {
html += indicators.getTimerIndicator(item).replace('indicatorIcon', 'indicatorIcon listItemAside');
}
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) {
html += '<span class="listViewUserDataButtons">';

View file

@ -54,7 +54,6 @@
.mediaInfoProgramAttribute {
color: #fff;
text-transform: uppercase;
background: #EF6C00;
padding: .16em .6em;
border-radius: .15em;
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) {
var html = '';
@ -6,23 +37,14 @@ define(['datetime', 'globalize', 'embyRouter', 'itemHelper', 'material-icons', '
var miscInfo = [];
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) {
try {
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) {
date = datetime.parseISO8601Date(item.EndDate);
@ -40,15 +62,22 @@ define(['datetime', 'globalize', 'embyRouter', 'itemHelper', 'material-icons', '
miscInfo.push('CH ' + item.ChannelNumber);
}
if (item.SeriesTimerId) {
miscInfo.push({
html: '<i class="md-icon mediaInfoItem mediaInfoTimerIcon mediaInfoIconItem">&#xE062;</i>'
});
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);
}
}
else if (item.TimerId) {
miscInfo.push({
html: '<i class="md-icon mediaInfoItem mediaInfoTimerIcon mediaInfoIconItem">&#xE061;</i>'
});
if (options.timerIndicator !== false) {
var timerHtml = getTimerIndicator(item);
if (timerHtml) {
miscInfo.push({
html: timerHtml
});
}
}
html += miscInfo.map(function (m) {
@ -159,22 +188,22 @@ define(['datetime', 'globalize', 'embyRouter', 'itemHelper', 'material-icons', '
if (item.IsLive) {
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) {
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) {
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) {
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));
}
else if (item.PremiereDate) {
else if (item.PremiereDate && options.originalAirDate !== false) {
try {
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);
}
else if (item.PremiereDate) {
try {
text = datetime.parseISO8601Date(item.PremiereDate).getFullYear();
miscInfo.push(text);
miscInfo.push(item.ProductionYear);
}
catch (e) {
console.log("Error parsing date: " + item.PremiereDate);
else if (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),
AirTime: form.querySelector('#txtAirTime').value,
Genres: editableListViewValues(form.querySelector("#listGenres")),
ProductionLocations: editableListViewValues(form.querySelector("#listCountries")),
Tags: editableListViewValues(form.querySelector("#listTags")),
Keywords: editableListViewValues(form.querySelector("#listKeywords")),
Studios: editableListViewValues(form.querySelector("#listStudios")).map(function (element) { return { Name: element }; }),
@ -683,12 +682,6 @@
showElement('#fldCustomRating', context);
}
if (item.Type == "Movie" || item.Type == "Trailer" || item.Type == "MusicArtist") {
showElement('#countriesCollapsible', context);
} else {
hideElement('#countriesCollapsible', context);
}
if (item.Type == "TvChannel") {
hideElement('#tagsCollapsible', context);
hideElement('#metadataSettingsCollapsible', context);
@ -809,7 +802,6 @@
el.checked = (item.AirDays || []).indexOf(el.getAttribute('data-day')) != -1;
});
populateListView(context.querySelector('#listCountries'), item.ProductionLocations || []);
populateListView(context.querySelector('#listGenres'), item.Genres);
populatePeople(context, item.People || []);

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