diff --git a/dashboard-ui/bower_components/emby-webcomponents/.bower.json b/dashboard-ui/bower_components/emby-webcomponents/.bower.json
index 20ce51b85c..1074005297 100644
--- a/dashboard-ui/bower_components/emby-webcomponents/.bower.json
+++ b/dashboard-ui/bower_components/emby-webcomponents/.bower.json
@@ -11,17 +11,16 @@
"homepage": "https://github.com/MediaBrowser/emby-webcomponents",
"dependencies": {
"requirejs": "requirejs#^2.1.22",
- "isMobile": "isMobile#^0.3.9",
- "material-design-lite": "material-design-lite#^1.1.2"
+ "isMobile": "isMobile#^0.3.9"
},
"devDependencies": {},
"ignore": [],
- "version": "1.3.52",
- "_release": "1.3.52",
+ "version": "1.4.51",
+ "_release": "1.4.51",
"_resolution": {
"type": "version",
- "tag": "1.3.52",
- "commit": "c00f1f1e92a8572cd01145ad02137e3eb74442fd"
+ "tag": "1.4.51",
+ "commit": "90b14ccc0e927221ab1d6c7556d1fadccf3876b9"
},
"_source": "https://github.com/MediaBrowser/emby-webcomponents.git",
"_target": "^1.2.0",
diff --git a/dashboard-ui/bower_components/emby-webcomponents/actionsheet/actionsheet.css b/dashboard-ui/bower_components/emby-webcomponents/actionsheet/actionsheet.css
index 1da4198430..298abfd7a5 100644
--- a/dashboard-ui/bower_components/emby-webcomponents/actionsheet/actionsheet.css
+++ b/dashboard-ui/bower_components/emby-webcomponents/actionsheet/actionsheet.css
@@ -27,7 +27,7 @@
text-align: center;
}
-.actionSheetMenuItem {
+button.actionSheetMenuItem {
padding: 0 1.6em;
margin: 0;
text-transform: none;
@@ -35,13 +35,22 @@
display: flex;
font-weight: inherit;
align-items: center;
+ flex-shrink: 0;
}
.actionSheetItemText {
padding: .8em 0;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ vertical-align: middle;
}
-.layout-tv .actionSheetMenuItem {
+.noflex .actionSheetItemText {
+ display: inline-block;
+}
+
+.layout-tv button.actionSheetMenuItem {
padding-top: .16em;
padding-bottom: .16em;
}
@@ -53,10 +62,15 @@
.actionSheetScroller {
/* Override default style being applied by polymer */
margin-bottom: 0 !important;
+ display: flex;
+ flex-direction: column;
+ width: 100%;
}
.layout-tv .actionSheetScroller {
max-height: 60%;
+ max-width: 60%;
+ width: auto;
}
h1.actionSheetTitle {
diff --git a/dashboard-ui/bower_components/emby-webcomponents/actionsheet/actionsheet.js b/dashboard-ui/bower_components/emby-webcomponents/actionsheet/actionsheet.js
index e3f7349f53..5aa2ac2952 100644
--- a/dashboard-ui/bower_components/emby-webcomponents/actionsheet/actionsheet.js
+++ b/dashboard-ui/bower_components/emby-webcomponents/actionsheet/actionsheet.js
@@ -1,4 +1,4 @@
-define(['dialogHelper', 'layoutManager', 'globalize', 'paper-button', 'css!./actionsheet', 'html!./../icons/nav.html', 'scrollStyles'], function (dialogHelper, layoutManager, globalize) {
+define(['dialogHelper', 'layoutManager', 'globalize', 'emby-button', 'css!./actionsheet', 'material-icons', 'scrollStyles'], function (dialogHelper, layoutManager, globalize) {
function parentWithClass(elem, className) {
@@ -48,6 +48,7 @@
function getPosition(options, dlg) {
var windowHeight = window.innerHeight;
+ var windowWidth = window.innerWidth;
if (windowHeight < 540) {
return null;
@@ -58,13 +59,23 @@
pos.top += options.positionTo.offsetHeight / 2;
pos.left += options.positionTo.offsetWidth / 2;
+ var height = dlg.offsetHeight || 300;
+ var width = dlg.offsetWidth || 160;
+
// Account for popup size
- pos.top -= ((dlg.offsetHeight || 300) / 2);
- pos.left -= ((dlg.offsetWidth || 160) / 2);
+ pos.top -= height / 2;
+ pos.left -= width / 2;
// Avoid showing too close to the bottom
- pos.top = Math.min(pos.top, windowHeight - 300);
- pos.left = Math.min(pos.left, window.innerWidth - 300);
+ var overflowX = pos.left + width - windowWidth;
+ var overflowY = pos.top + height - windowHeight;
+
+ if (overflowX > 0) {
+ pos.left -= (overflowX + 20);
+ }
+ if (overflowY > 0) {
+ pos.top -= (overflowY + 20);
+ }
// Do some boundary checking
pos.top = Math.max(pos.top, 10);
@@ -130,46 +141,51 @@
}
}
- html += '
';
+ var scrollType = layoutManager.desktop ? 'smoothScrollY' : 'hiddenScrollY';
- options.items.forEach(function (o) {
- o.ironIcon = o.selected ? 'nav:check' : null;
- });
+ html += '
';
@@ -190,32 +206,30 @@
// Seeing an issue in some non-chrome browsers where this is requiring a double click
//var eventName = browser.firefox ? 'mousedown' : 'click';
- var eventName = 'click';
+ var selectedId;
+
+ dlg.addEventListener('click', function (e) {
+
+ var actionSheetMenuItem = parentWithClass(e.target, 'actionSheetMenuItem');
+
+ if (actionSheetMenuItem) {
+ selectedId = actionSheetMenuItem.getAttribute('data-id');
+ dialogHelper.close(dlg);
+ }
+
+ });
return new Promise(function (resolve, reject) {
- dlg.addEventListener(eventName, function (e) {
+ dlg.addEventListener('close', function () {
- var actionSheetMenuItem = parentWithClass(e.target, 'actionSheetMenuItem');
+ if (selectedId != null) {
+ if (options.callback) {
+ options.callback(selectedId);
+ }
- if (actionSheetMenuItem) {
-
- var selectedId = actionSheetMenuItem.getAttribute('data-id');
-
- dialogHelper.close(dlg);
-
- // Add a delay here to allow the click animation to finish, for nice effect
- setTimeout(function () {
-
- if (options.callback) {
- options.callback(selectedId);
- }
-
- resolve(selectedId);
-
- }, 100);
+ resolve(selectedId);
}
-
});
dialogHelper.open(dlg);
diff --git a/dashboard-ui/bower_components/emby-webcomponents/alert/alert.js b/dashboard-ui/bower_components/emby-webcomponents/alert/alert.js
index 31bf70a203..6995d3e1a5 100644
--- a/dashboard-ui/bower_components/emby-webcomponents/alert/alert.js
+++ b/dashboard-ui/bower_components/emby-webcomponents/alert/alert.js
@@ -1,10 +1,10 @@
-define(['dialogHelper', 'layoutManager', 'globalize', 'html!./../icons/nav.html', 'css!./../prompt/style.css', 'paper-button', 'paper-icon-button-light', 'paper-input'], function (dialogHelper, layoutManager, globalize) {
+define(['dialogHelper', 'layoutManager', 'globalize', 'material-icons', 'css!./../prompt/style.css', 'emby-button', 'paper-icon-button-light'], function (dialogHelper, layoutManager, globalize) {
function getIcon(icon, cssClass, canFocus, autoFocus) {
var tabIndex = canFocus ? '' : ' tabindex="-1"';
autoFocus = autoFocus ? ' autofocus' : '';
- return '
';
+ return '
';
}
return function (options) {
@@ -44,7 +44,7 @@ define(['dialogHelper', 'layoutManager', 'globalize', 'html!./../icons/nav.html'
html += '
';
if (backButton) {
- html += getIcon('dialog:arrow-back', 'btnPromptExit', false);
+ html += getIcon('arrow_back', 'btnPromptExit', false);
}
if (options.title) {
@@ -72,10 +72,10 @@ define(['dialogHelper', 'layoutManager', 'globalize', 'html!./../icons/nav.html'
var buttonText = options.type == 'error' ? 'sharedcomponents#ButtonOk' : 'sharedcomponents#ButtonGotIt';
if (raisedButtons) {
- html += '
' + globalize.translate(buttonText) + '';
+ html += '
';
} else {
html += '
';
}
diff --git a/dashboard-ui/bower_components/emby-webcomponents/alphapicker/alphapicker.js b/dashboard-ui/bower_components/emby-webcomponents/alphapicker/alphapicker.js
new file mode 100644
index 0000000000..8f790d7a77
--- /dev/null
+++ b/dashboard-ui/bower_components/emby-webcomponents/alphapicker/alphapicker.js
@@ -0,0 +1,279 @@
+define(['focusManager', 'css!./style.css', 'clearButtonStyle', 'paper-icon-button-light', 'material-icons'], function (focusManager) {
+
+ function focus() {
+ var selected = this.querySelector('.selected');
+
+ if (selected) {
+ focusManager.focus(selected);
+ } else {
+ focusManager.autoFocus(this, true);
+ }
+ }
+
+ function getLetterButton(l) {
+ return '
';
+ }
+
+ function render(element, options) {
+
+ element.classList.add('alphaPicker');
+ element.classList.add('focuscontainer-x');
+
+ var html = '';
+ var letters;
+
+ html += '
';
+ if (options.mode == 'keyboard') {
+ html += '';
+ } else {
+ letters = ['#'];
+ html += letters.map(getLetterButton).join('');
+ }
+
+ 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') {
+ html += '';
+ html += '
';
+
+ letters = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
+ html += '
';
+ html += '
';
+ html += letters.map(getLetterButton).join('');
+ html += '
';
+ } else {
+ html += '
';
+ }
+
+ element.innerHTML = html;
+
+ element.classList.add('focusable');
+ element.focus = focus;
+ }
+
+ function alphaPicker(options) {
+
+ var self = this;
+
+ var element = options.element;
+ var itemsContainer = options.itemsContainer;
+ var itemClass = options.itemClass;
+
+ var itemFocusValue;
+ var itemFocusTimeout;
+
+ function onItemFocusTimeout() {
+ itemFocusTimeout = null;
+ self.value(itemFocusValue);
+ }
+
+ var alphaFocusedElement;
+ var alphaFocusTimeout;
+
+ function onAlphaFocusTimeout() {
+
+ alphaFocusTimeout = null;
+
+ if (document.activeElement == alphaFocusedElement) {
+ var value = alphaFocusedElement.getAttribute('data-value');
+ self.value(value, true);
+ }
+ }
+
+ function parentWithClass(elem, className) {
+
+ while (!elem.classList || !elem.classList.contains(className)) {
+ elem = elem.parentNode;
+
+ if (!elem) {
+ return null;
+ }
+ }
+
+ return elem;
+ }
+
+ function onAlphaPickerInKeyboardModeClick(e) {
+
+ var alphaPickerButton = parentWithClass(e.target, 'alphaPickerButton');
+
+ if (alphaPickerButton) {
+ var value = alphaPickerButton.getAttribute('data-value');
+
+ element.dispatchEvent(new CustomEvent("alphavalueclicked", {
+ detail: {
+ value: value
+ }
+ }));
+ }
+ }
+
+ function onAlphaPickerClick(e) {
+
+ var alphaPickerButton = parentWithClass(e.target, 'alphaPickerButton');
+
+ if (alphaPickerButton) {
+ var value = alphaPickerButton.getAttribute('data-value');
+
+ if (currentValue == value.toUpperCase()) {
+ self.value(null, true);
+ } else {
+ self.value(value, true);
+ }
+ }
+ }
+
+ function onAlphaPickerFocusIn(e) {
+
+ if (alphaFocusTimeout) {
+ clearTimeout(alphaFocusTimeout);
+ alphaFocusTimeout = null;
+ }
+
+ var alphaPickerButton = parentWithClass(e.target, 'alphaPickerButton');
+
+ if (alphaPickerButton) {
+ alphaFocusedElement = alphaPickerButton;
+ alphaFocusTimeout = setTimeout(onAlphaFocusTimeout, 100);
+ }
+ }
+
+ function onItemsFocusIn(e) {
+
+ var item = parentWithClass(e.target, itemClass);
+
+ if (item) {
+ var prefix = item.getAttribute('data-prefix');
+ if (prefix && prefix.length) {
+
+ itemFocusValue = prefix[0];
+ if (itemFocusTimeout) {
+ clearTimeout(itemFocusTimeout);
+ }
+ itemFocusTimeout = setTimeout(onItemFocusTimeout, 100);
+ }
+ }
+ }
+
+ self.enabled = function (enabled) {
+
+ if (enabled) {
+
+ if (itemsContainer) {
+ itemsContainer.addEventListener('focus', onItemsFocusIn, true);
+ }
+
+ if (options.mode == 'keyboard') {
+ element.addEventListener('click', onAlphaPickerInKeyboardModeClick);
+ }
+
+ if (options.valueChangeEvent !== 'click') {
+ element.addEventListener('focus', onAlphaPickerFocusIn, true);
+ } else {
+ element.addEventListener('click', onAlphaPickerClick);
+ }
+
+ } else {
+
+ if (itemsContainer) {
+ itemsContainer.removeEventListener('focus', onItemsFocusIn, true);
+ }
+
+ element.removeEventListener('click', onAlphaPickerInKeyboardModeClick);
+ element.removeEventListener('focus', onAlphaPickerFocusIn, true);
+ element.removeEventListener('click', onAlphaPickerClick);
+ }
+ };
+
+ self.on = function (name, fn) {
+ element.addEventListener(name, fn);
+ };
+
+ self.off = function (name, fn) {
+ element.removeEventListener(name, fn);
+ };
+
+ self.destroy = function () {
+
+ self.enabled(false);
+ element.classList.remove('focuscontainer-x');
+ };
+
+ self.visible = function (visible) {
+
+ element.style.visibility = visible ? 'visible' : 'hidden';
+ };
+
+ var currentValue;
+ self.value = function (value, applyValue) {
+
+ var btn, selected;
+
+ if (value !== undefined) {
+ if (value != null) {
+
+ value = value.toUpperCase();
+ currentValue = value;
+
+ if (options.mode != 'keyboard') {
+ selected = element.querySelector('.selected');
+ btn = element.querySelector('.alphaPickerButton[data-value=\'' + value + '\']');
+
+ if (btn && btn != selected) {
+ btn.classList.add('selected');
+ }
+ if (selected && selected != btn) {
+ selected.classList.remove('selected');
+ }
+ }
+ } else {
+ currentValue = value;
+
+ selected = element.querySelector('.selected');
+ if (selected) {
+ selected.classList.remove('selected');
+ }
+ }
+ }
+
+ if (applyValue) {
+ element.dispatchEvent(new CustomEvent("alphavaluechanged", {
+ detail: {
+ value: value
+ }
+ }));
+ }
+
+ return currentValue;
+ };
+
+ self.values = function () {
+
+ var elems = element.querySelectorAll('.alphaPickerButton');
+ var values = [];
+ for (var i = 0, length = elems.length; i < length; i++) {
+
+ values.push(elems[i].getAttribute('data-value'));
+
+ }
+
+ return values;
+ };
+
+ self.focus = function () {
+ focusManager.autoFocus(element, true);
+ };
+
+ render(element, options);
+
+ self.enabled(true);
+ self.visible(true);
+ }
+
+ return alphaPicker;
+});
\ No newline at end of file
diff --git a/dashboard-ui/bower_components/emby-webcomponents/alphapicker/style.css b/dashboard-ui/bower_components/emby-webcomponents/alphapicker/style.css
new file mode 100644
index 0000000000..b9b5296676
--- /dev/null
+++ b/dashboard-ui/bower_components/emby-webcomponents/alphapicker/style.css
@@ -0,0 +1,52 @@
+.alphaPicker {
+ text-align: center;
+ display: flex;
+ flex-direction: column;
+}
+
+.alphaPickerRow {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-direction: row;
+}
+
+.alphaPicker.vertical .alphaPickerRow {
+ flex-direction: column;
+}
+
+button.alphaPickerButton {
+ min-width: initial;
+ margin: 0;
+ padding: .1em .4em !important;
+ width: auto;
+ border-radius: .1em;
+ font-weight: normal;
+ opacity: .25;
+}
+
+.vertical .alphaPickerButton {
+ padding: .25em .4em !important;
+}
+
+.layout-desktop .alphaPickerButton {
+ opacity: .7;
+}
+
+[is=paper-icon-button-light].alphaPickerButton i {
+ width: 3.3vh;
+ height: 3.3vh;
+ font-size: 3.3vh;
+}
+
+.alphaPickerButton.selected {
+ color: #000;
+ background-color: #bbb;
+ opacity: 1;
+}
+
+.layout-tv .alphaPickerButton:focus {
+ background-color: #52B54B;
+ opacity: 1;
+ color: #fff;
+}
diff --git a/dashboard-ui/bower_components/emby-webcomponents/appsettings.js b/dashboard-ui/bower_components/emby-webcomponents/appsettings.js
index e5fd7aca26..ab6d4e07fc 100644
--- a/dashboard-ui/bower_components/emby-webcomponents/appsettings.js
+++ b/dashboard-ui/bower_components/emby-webcomponents/appsettings.js
@@ -13,6 +13,15 @@ define(['appStorage', 'events'], function (appStorage, events) {
var self = this;
+ self.enableAutoLogin = function (val) {
+
+ if (val != null) {
+ self.set('enableAutoLogin', val.toString());
+ }
+
+ return self.get('enableAutoLogin') != 'false';
+ };
+
self.enableAutomaticBitrateDetection = function (val) {
if (val != null) {
diff --git a/dashboard-ui/bower_components/emby-webcomponents/backdrop/backdrop.js b/dashboard-ui/bower_components/emby-webcomponents/backdrop/backdrop.js
index 43eb979a67..5b48e8a52a 100644
--- a/dashboard-ui/bower_components/emby-webcomponents/backdrop/backdrop.js
+++ b/dashboard-ui/bower_components/emby-webcomponents/backdrop/backdrop.js
@@ -1,8 +1,9 @@
-define(['browser', 'css!./style'], function (browser) {
+define(['browser', 'connectionManager', 'playbackManager', 'css!./style'], function (browser, connectionManager, playbackManager) {
function enableAnimation(elem) {
if (browser.mobile) {
+ i
return false;
}
@@ -99,6 +100,8 @@
function clearBackdrop(clearAll) {
+ clearRotation();
+
if (currentLoadingBackdrop) {
currentLoadingBackdrop.destroy();
currentLoadingBackdrop = null;
@@ -114,16 +117,18 @@
}
var skinContainer;
- function setSkinContainerBackgroundEnabled() {
-
+ function getSkinContainer() {
if (!skinContainer) {
skinContainer = document.querySelector('.skinContainer');
}
+ return skinContainer;
+ }
+ function setSkinContainerBackgroundEnabled() {
if (hasInternalBackdrop || hasExternalBackdrop) {
- skinContainer.classList.add('withBackdrop');
+ getSkinContainer().classList.add('withBackdrop');
} else {
- skinContainer.classList.remove('withBackdrop');
+ getSkinContainer().classList.remove('withBackdrop');
}
}
@@ -166,58 +171,145 @@
currentLoadingBackdrop = instance;
}
- function setBackdrops(items) {
+ var windowWidth;
+ function resetWindowSize() {
+ windowWidth = screen.availWidth || window.innerWidth;
+ }
+ window.addEventListener("orientationchange", resetWindowSize);
+ window.addEventListener('resize', resetWindowSize);
+ resetWindowSize();
- var images = items.map(function (i) {
+ function getItemImageUrls(item) {
- if (i.BackdropImageTags && i.BackdropImageTags.length > 0) {
- return {
- id: i.Id,
- tag: i.BackdropImageTags[0],
- serverId: i.ServerId
- };
- }
+ var apiClient = connectionManager.getApiClient(item.ServerId);
- if (i.ParentBackdropItemId && i.ParentBackdropImageTags && i.ParentBackdropImageTags.length) {
+ if (item.BackdropImageTags && item.BackdropImageTags.length > 0) {
- return {
- id: i.ParentBackdropItemId,
- tag: i.ParentBackdropImageTags[0],
- serverId: i.ServerId
- };
- }
- return null;
+ return item.BackdropImageTags.map(function (imgTag, index) {
- }).filter(function (i) {
- return i != null;
- });
+ return apiClient.getScaledImageUrl(item.Id, {
+ type: "Backdrop",
+ tag: imgTag,
+ maxWidth: Math.min(windowWidth, 1920),
+ index: index
+ });
+ });
+ }
+ if (item.ParentBackdropItemId && item.ParentBackdropImageTags && item.ParentBackdropImageTags.length) {
+
+ return item.ParentBackdropImageTags.map(function (imgTag, index) {
+
+ return apiClient.getScaledImageUrl(item.ParentBackdropItemId, {
+ type: "Backdrop",
+ tag: imgTag,
+ maxWidth: Math.min(windowWidth, 1920),
+ index: index
+ });
+ });
+ }
+
+ return [];
+ }
+
+ function getImageUrls(items) {
+
+ var list = [];
+
+ for (var i = 0, length = items.length; i < length; i++) {
+
+ var itemImages = getItemImageUrls(items[i]);
+
+ itemImages.forEach(function (img) {
+ list.push(img);
+ });
+ }
+
+ 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 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;
+ }
+ return true;
+ }
+
+ var rotationInterval;
+ var currentRotatingImages = [];
+ var currentRotationIndex = -1;
+ function setBackdrops(items, imageSetId) {
+
+ var images = getImageUrls(items);
+
+ imageSetId = imageSetId || new Date().getTime();
if (images.length) {
- var index = getRandom(0, images.length - 1);
- var item = images[index];
-
- require(['connectionManager'], function (connectionManager) {
-
- var apiClient = connectionManager.getApiClient(item.serverId);
- var imgUrl = apiClient.getScaledImageUrl(item.id, {
- type: "Backdrop",
- tag: item.tag,
- //maxWidth: window.innerWidth,
- quality: 100
- });
-
- setBackdrop(imgUrl);
- });
+ startRotation(images, imageSetId);
} else {
clearBackdrop();
}
}
+ function startRotation(images) {
+
+ if (arraysEqual(images, currentRotatingImages)) {
+ return;
+ }
+
+ clearRotation();
+
+ currentRotatingImages = images;
+ currentRotationIndex = -1;
+
+ if (images.length > 1) {
+ rotationInterval = setInterval(onRotationInterval, 20000);
+ }
+ onRotationInterval();
+ }
+
+ function onRotationInterval() {
+
+ if (playbackManager.isPlayingVideo()) {
+ return;
+ }
+
+ var newIndex = currentRotationIndex + 1;
+ if (newIndex >= currentRotatingImages.length) {
+ newIndex = 0;
+ }
+
+ currentRotationIndex = newIndex;
+ setBackdropImage(currentRotatingImages[newIndex]);
+ }
+
+ function clearRotation() {
+ var interval = rotationInterval;
+ if (interval) {
+ clearInterval(interval);
+ }
+ rotationInterval = null;
+ currentRotatingImages = [];
+ currentRotationIndex = -1;
+ }
+
function setBackdrop(url) {
+ if (typeof url !== 'string') {
+ url = getImageUrls([url])[0];
+ }
+
if (url) {
+ clearRotation();
+
setBackdropImage(url);
} else {
diff --git a/dashboard-ui/bower_components/emby-webcomponents/backdrop/style.css b/dashboard-ui/bower_components/emby-webcomponents/backdrop/style.css
index d60beb08e8..8055b653d3 100644
--- a/dashboard-ui/bower_components/emby-webcomponents/backdrop/style.css
+++ b/dashboard-ui/bower_components/emby-webcomponents/backdrop/style.css
@@ -1,3 +1,7 @@
+.backdropContainer {
+ contain: layout style;
+}
+
.backdropImage {
background-repeat: no-repeat;
background-position: center center;
@@ -8,4 +12,5 @@
left: 0;
right: 0;
bottom: 0;
-}
\ No newline at end of file
+ contain: layout style;
+}
diff --git a/dashboard-ui/bower_components/emby-webcomponents/bower.json b/dashboard-ui/bower_components/emby-webcomponents/bower.json
index 0366d51910..0a6c6d4d1d 100644
--- a/dashboard-ui/bower_components/emby-webcomponents/bower.json
+++ b/dashboard-ui/bower_components/emby-webcomponents/bower.json
@@ -11,8 +11,7 @@
"homepage": "https://github.com/MediaBrowser/emby-webcomponents",
"dependencies": {
"requirejs": "requirejs#^2.1.22",
- "isMobile": "isMobile#^0.3.9",
- "material-design-lite": "material-design-lite#^1.1.2"
+ "isMobile": "isMobile#^0.3.9"
},
"devDependencies": {
diff --git a/dashboard-ui/bower_components/emby-webcomponents/browser.js b/dashboard-ui/bower_components/emby-webcomponents/browser.js
index c973fdbb09..0957fc1340 100644
--- a/dashboard-ui/bower_components/emby-webcomponents/browser.js
+++ b/dashboard-ui/bower_components/emby-webcomponents/browser.js
@@ -101,5 +101,7 @@
browser.tv = isTv();
browser.operaTv = browser.tv && userAgent.toLowerCase().indexOf('opr/') != -1;
+ browser.noFlex = browser.tv && !browser.chrome && !browser.operaTv;
+
return browser;
});
\ No newline at end of file
diff --git a/dashboard-ui/bower_components/emby-webcomponents/browserdeviceprofile.js b/dashboard-ui/bower_components/emby-webcomponents/browserdeviceprofile.js
index c59e533dc4..39050760ee 100644
--- a/dashboard-ui/bower_components/emby-webcomponents/browserdeviceprofile.js
+++ b/dashboard-ui/bower_components/emby-webcomponents/browserdeviceprofile.js
@@ -151,6 +151,11 @@ define(['browser'], function (browser) {
function getMaxBitrate() {
+ // 10mbps
+ if (browser.xboxOne) {
+ return 10000000;
+ }
+
var userAgent = navigator.userAgent.toLowerCase();
if (browser.tizen) {
diff --git a/dashboard-ui/bower_components/emby-webcomponents/collectioneditor/collectioneditor.js b/dashboard-ui/bower_components/emby-webcomponents/collectioneditor/collectioneditor.js
new file mode 100644
index 0000000000..9fd2d8c24f
--- /dev/null
+++ b/dashboard-ui/bower_components/emby-webcomponents/collectioneditor/collectioneditor.js
@@ -0,0 +1,280 @@
+define(['shell', 'dialogHelper', 'loading', 'layoutManager', 'connectionManager', 'scrollHelper', 'embyRouter', 'globalize', 'emby-checkbox', 'emby-input', 'paper-icon-button-light', 'emby-select', 'material-icons', 'css!./../formdialog', 'emby-button'], function (shell, dialogHelper, loading, layoutManager, connectionManager, scrollHelper, embyRouter, globalize) {
+
+ var currentServerId;
+
+ function parentWithClass(elem, className) {
+
+ while (!elem.classList || !elem.classList.contains(className)) {
+ elem = elem.parentNode;
+
+ if (!elem) {
+ return null;
+ }
+ }
+
+ return elem;
+ }
+
+ function onSubmit(e) {
+ loading.show();
+
+ var panel = parentWithClass(this, 'dialog');
+
+ var collectionId = panel.querySelector('#selectCollectionToAddTo').value;
+
+ var apiClient = connectionManager.getApiClient(currentServerId);
+
+ if (collectionId) {
+ addToCollection(apiClient, panel, collectionId);
+ } else {
+ createCollection(apiClient, panel);
+ }
+
+ e.preventDefault();
+ return false;
+ }
+
+ function createCollection(apiClient, dlg) {
+
+ var url = apiClient.getUrl("Collections", {
+
+ Name: dlg.querySelector('#txtNewCollectionName').value,
+ IsLocked: !dlg.querySelector('#chkEnableInternetMetadata').checked,
+ Ids: dlg.querySelector('.fldSelectedItemIds').value || ''
+
+ //ParentId: getParameterByName('parentId') || LibraryMenu.getTopParentId()
+
+ });
+
+ apiClient.ajax({
+ type: "POST",
+ url: url,
+ dataType: "json"
+
+ }).then(function (result) {
+
+ loading.hide();
+
+ var id = result.Id;
+
+ dialogHelper.close(dlg);
+ redirectToCollection(apiClient, id);
+
+ });
+ }
+
+ function redirectToCollection(apiClient, id) {
+
+ apiClient.getItem(apiClient.getCurrentUserId(), id).then(function (item) {
+
+ embyRouter.showItem(item);
+ });
+ }
+
+ function addToCollection(apiClient, dlg, id) {
+
+ var url = apiClient.getUrl("Collections/" + id + "/Items", {
+
+ Ids: dlg.querySelector('.fldSelectedItemIds').value || ''
+ });
+
+ apiClient.ajax({
+ type: "POST",
+ url: url
+
+ }).then(function () {
+
+ loading.hide();
+
+ dialogHelper.close(dlg);
+
+ require(['toast'], function (toast) {
+ toast(globalize.translate('sharedcomponents#MessageItemsAdded'));
+ });
+ });
+ }
+
+ function triggerChange(select) {
+ select.dispatchEvent(new CustomEvent('change', {}));
+ }
+
+ function populateCollections(panel) {
+
+ loading.show();
+
+ var select = panel.querySelector('#selectCollectionToAddTo');
+
+ panel.querySelector('.newCollectionInfo').classList.add('hide');
+
+ var options = {
+
+ Recursive: true,
+ IncludeItemTypes: "BoxSet",
+ SortBy: "SortName"
+ };
+
+ var apiClient = connectionManager.getApiClient(currentServerId);
+ apiClient.getItems(apiClient.getCurrentUserId(), options).then(function (result) {
+
+ var html = '';
+
+ html += '
';
+
+ html += result.Items.map(function (i) {
+
+ return '
';
+ });
+
+ select.innerHTML = html;
+ select.value = '';
+ triggerChange(select);
+
+ loading.hide();
+ });
+ }
+
+ function getEditorHtml() {
+
+ var html = '';
+
+ html += '
';
+ html += '
';
+ html += '
';
+ html += '
';
+ html += '
';
+
+ return html;
+ }
+
+ function onHelpClick(e) {
+
+ shell.openUrl(this.href);
+ e.preventDefault();
+ return false;
+ }
+
+ function initEditor(content, items) {
+
+ content.querySelector('#selectCollectionToAddTo').addEventListener('change', function () {
+ if (this.value) {
+ content.querySelector('.newCollectionInfo').classList.add('hide');
+ content.querySelector('#txtNewCollectionName').removeAttribute('required');
+ } else {
+ content.querySelector('.newCollectionInfo').classList.remove('hide');
+ content.querySelector('#txtNewCollectionName').setAttribute('required', 'required');
+ }
+ });
+
+ content.querySelector('form').addEventListener('submit', onSubmit);
+
+ content.querySelector('.fldSelectedItemIds', content).value = items.join(',');
+
+ if (items.length) {
+ content.querySelector('.fldSelectCollection').classList.remove('hide');
+ populateCollections(content);
+ } else {
+ content.querySelector('.fldSelectCollection').classList.add('hide');
+
+ var selectCollectionToAddTo = content.querySelector('#selectCollectionToAddTo');
+ selectCollectionToAddTo.innerHTML = '';
+ selectCollectionToAddTo.value = '';
+ triggerChange(selectCollectionToAddTo);
+ }
+ }
+
+ function collectioneditor() {
+
+ var self = this;
+
+ self.show = function (options) {
+
+ var items = options.items || {};
+ currentServerId = options.serverId;
+
+ 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 = '';
+ var title = items.length ? globalize.translate('sharedcomponents#AddToCollection') : globalize.translate('sharedcomponents#NewCollection');
+
+ html += '';
+
+ html += getEditorHtml();
+
+ dlg.innerHTML = html;
+ document.body.appendChild(dlg);
+
+ initEditor(dlg, items);
+
+ dlg.querySelector('.btnCancel').addEventListener('click', function () {
+
+ dialogHelper.close(dlg);
+ });
+
+ if (layoutManager.tv) {
+ scrollHelper.centerFocus.on(dlg.querySelector('.dialogContent'), false);
+ }
+
+ return new Promise(function (resolve, reject) {
+
+ dlg.addEventListener('close', resolve);
+ dialogHelper.open(dlg);
+ });
+ };
+ }
+
+ return collectioneditor;
+});
\ No newline at end of file
diff --git a/dashboard-ui/bower_components/emby-webcomponents/confirm/confirm.js b/dashboard-ui/bower_components/emby-webcomponents/confirm/confirm.js
index be5bf19896..fbce2372eb 100644
--- a/dashboard-ui/bower_components/emby-webcomponents/confirm/confirm.js
+++ b/dashboard-ui/bower_components/emby-webcomponents/confirm/confirm.js
@@ -74,9 +74,9 @@ define(['layoutManager', 'globalize'], function (layoutManager, globalize) {
html += '
';
@@ -106,7 +106,7 @@ define(['layoutManager', 'globalize'], function (layoutManager, globalize) {
function showConfirm(options) {
return new Promise(function (resolve, reject) {
- require(['dialogHelper', 'paper-button'], function (dialogHelper) {
+ require(['dialogHelper', 'emby-button'], function (dialogHelper) {
showConfirmInternal(options, dialogHelper, resolve, reject);
});
});
diff --git a/dashboard-ui/bower_components/emby-webcomponents/dialoghelper/dialoghelper.css b/dashboard-ui/bower_components/emby-webcomponents/dialoghelper/dialoghelper.css
index 831a69a97b..6ad6be829a 100644
--- a/dashboard-ui/bower_components/emby-webcomponents/dialoghelper/dialoghelper.css
+++ b/dashboard-ui/bower_components/emby-webcomponents/dialoghelper/dialoghelper.css
@@ -10,6 +10,7 @@
border: 0;
padding: 0;
will-change: transform;
+ contain: style;
}
.dialog.fixedSize {
@@ -29,6 +30,7 @@
top: 50%;
left: 50%;
max-width: 70%;
+ max-height: 84%;
}
@media all and (min-width: 1280px) and (min-height: 720px) {
@@ -92,7 +94,7 @@
left: 0 !important;
right: 0 !important;
margin: 0 !important;
- z-index: 999998 !important;
+ z-index: 999999 !important;
transition: opacity ease-out 0.2s;
}
diff --git a/dashboard-ui/bower_components/emby-webcomponents/dialoghelper/dialoghelper.js b/dashboard-ui/bower_components/emby-webcomponents/dialoghelper/dialoghelper.js
index 3a3e8b638d..33589dbe72 100644
--- a/dashboard-ui/bower_components/emby-webcomponents/dialoghelper/dialoghelper.js
+++ b/dashboard-ui/bower_components/emby-webcomponents/dialoghelper/dialoghelper.js
@@ -2,6 +2,19 @@
var globalOnOpenCallback;
+ function enableAnimation() {
+
+ if (browser.animate) {
+ return true;
+ }
+
+ if (browser.edge) {
+ return true;
+ }
+
+ return false;
+ }
+
function dialogHashHandler(dlg, hash, resolve) {
var self = this;
@@ -129,8 +142,8 @@
dlg.addEventListener('click', function (event) {
var rect = dlg.getBoundingClientRect();
- var isInDialog = (rect.top <= event.clientY && event.clientY <= rect.top + rect.height
- && rect.left <= event.clientX && event.clientX <= rect.left + rect.width);
+ var isInDialog = (rect.top <= event.clientY && event.clientY <= (rect.top + rect.height)
+ && rect.left <= event.clientX && event.clientX <= (rect.left + rect.width));
if (!isInDialog) {
if (parentWithTag(event.target, 'SELECT')) {
@@ -150,7 +163,7 @@
// Without this, seeing some script errors in Firefox
// Also for some reason it won't auto-focus without a delay here, still investigating that
- var delay = browser.animate ? 0 : 300;
+ var delay = enableAnimation() ? 300 : 300;
setTimeout(function () {
focusManager.autoFocus(dlg);
@@ -167,7 +180,7 @@
var backdrop = document.createElement('div');
backdrop.classList.add('dialogBackdrop');
- dlg.parentNode.insertBefore(backdrop, dlg.nextSibling);
+ dlg.parentNode.insertBefore(backdrop, dlg);
dlg.backdrop = backdrop;
// Doing this immediately causes the opacity to jump immediately without animating
@@ -240,6 +253,15 @@
return elem.animate(keyframes, timing).onfinish = onFinish;
}
+ function scaleDown(elem) {
+
+ var keyframes = [
+ { transform: 'none', opacity: 1, offset: 0 },
+ { transform: 'scale(0)', opacity: 0, offset: 1 }];
+ var timing = elem.animationConfig.exit.timing;
+ return elem.animate(keyframes, timing);
+ }
+
function fadeOut(elem) {
var keyframes = [
@@ -282,6 +304,8 @@
if (dlg.animationConfig.exit.name == 'fadeout') {
animation = fadeOut(dlg);
+ } else if (dlg.animationConfig.exit.name == 'scaledown') {
+ animation = scaleDown(dlg);
} else if (dlg.animationConfig.exit.name == 'slidedown') {
animation = slideDown(dlg);
} else {
@@ -386,33 +410,40 @@
dlg.setAttribute('data-autofocus', 'true');
}
- var defaultEntryAnimation = browser.animate ? 'scaleup' : 'fadein';
- dlg.entryAnimation = options.entryAnimation || defaultEntryAnimation;
- dlg.exitAnimation = 'fadeout';
+ var defaultEntryAnimation = 'scaleup';
+ var entryAnimation = options.entryAnimation || defaultEntryAnimation;
+ var defaultExitAnimation = 'scaledown';
+ var exitAnimation = options.exitAnimation || defaultExitAnimation;
// If it's not fullscreen then lower the default animation speed to make it open really fast
var entryAnimationDuration = options.entryAnimationDuration || (options.size ? 200 : 300);
+ var exitAnimationDuration = options.exitAnimationDuration || (options.size ? 200 : 300);
dlg.animationConfig = {
// scale up
'entry': {
- name: dlg.entryAnimation,
+ name: entryAnimation,
node: dlg,
- timing: { duration: entryAnimationDuration, easing: 'ease-out' }
+ timing: {
+ duration: entryAnimationDuration,
+ easing: 'ease-out'
+ }
},
// fade out
'exit': {
- name: dlg.exitAnimation,
+ name: exitAnimation,
node: dlg,
- timing: { duration: options.exitAnimationDuration || 300, easing: 'ease-in' }
+ timing: {
+ duration: exitAnimationDuration,
+ easing: 'ease-out',
+ fill: 'both'
+ }
}
};
// too buggy in IE, not even worth it
- if (!browser.animate) {
+ if (!enableAnimation()) {
dlg.animationConfig = null;
- dlg.entryAnimation = null;
- dlg.exitAnimation = null;
}
dlg.classList.add('dialog');
diff --git a/dashboard-ui/bower_components/emby-webcomponents/emby-button/emby-button.css b/dashboard-ui/bower_components/emby-webcomponents/emby-button/emby-button.css
new file mode 100644
index 0000000000..50f0c0d6b5
--- /dev/null
+++ b/dashboard-ui/bower_components/emby-webcomponents/emby-button/emby-button.css
@@ -0,0 +1,250 @@
+[is="emby-button"] {
+ position: relative;
+ display: inline-block;
+ align-items: center;
+ box-sizing: border-box;
+ margin: 0 .29em;
+ background: transparent;
+ text-align: center;
+ font-size: inherit;
+ font-family: inherit;
+ color: inherit;
+ outline-width: 0;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ -webkit-user-select: none;
+ user-select: none;
+ cursor: pointer;
+ z-index: 0;
+ padding: 0.7em 0.57em;
+ font-weight: normal;
+ vertical-align: middle;
+ border: 0;
+ vertical-align: middle;
+ border-radius: 3px;
+ /* These are getting an outline in opera tv browsers, which run chrome 30 */
+ outline: none !important;
+ position: relative;
+ overflow: hidden;
+ font-weight: 500;
+ text-transform: uppercase;
+}
+
+ [is="emby-button"].raised, [is="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);
+ }
+
+ [is="emby-button"].fab {
+ display: inline-flex;
+ border-radius: 50%;
+ min-width: 56px;
+ min-height: 56px;
+ height: 5.2vh;
+ width: 5.2vh;
+ background-color: #444;
+ padding: .6em;
+ box-sizing: border-box;
+ align-items: center;
+ justify-content: center;
+ text-align: center;
+ color: #fff !important;
+ margin: 0;
+ }
+
+ [is="emby-button"].fab i {
+ height: 4.4vh;
+ width: 4.4vh;
+ vertical-align: middle;
+ font-size: 4.4vh;
+ }
+
+ [is="emby-button"].noflex {
+ display: inline-block;
+ }
+
+ [is="emby-button"].fab.mini:not(.autoSize) {
+ min-width: 40px !important;
+ min-height: 40px !important;
+ height: 3.3vh !important;
+ width: 3.3vh !important;
+ }
+
+ [is="emby-button"].fab.mini {
+ padding: .4em;
+ }
+
+ [is="emby-button"].fab.mini i {
+ height: 2.4vh !important;
+ width: 2.4vh !important;
+ font-size: 2.4vh !important;
+ }
+
+ [is="emby-button"].fab iron-icon {
+ width: 100%;
+ height: 100%;
+ vertical-align: middle;
+ }
+
+ [is="emby-button"].fab i {
+ vertical-align: middle;
+ }
+
+ [is="emby-button"].block {
+ display: block;
+ align-items: center;
+ justify-content: center;
+ margin: .25em 0;
+ width: 100%;
+ }
+
+ [is="emby-button"].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);
+ }
+
+ [is="emby-button"] iron-icon + span {
+ margin-left: .5em;
+ }
+
+ [is="emby-button"] i + span {
+ margin-left: .5em;
+ }
+
+[is=emby-button].autoSize {
+ width: auto !important;
+ height: auto !important;
+ min-height: initial !important;
+ min-width: initial !important;
+}
+
+[is=paper-icon-button-light] {
+ position: relative;
+ display: inline-flex;
+ align-items: center;
+ box-sizing: border-box;
+ margin: 0 .29em;
+ background: transparent;
+ text-align: center;
+ font-size: inherit;
+ font-family: inherit;
+ color: inherit;
+ outline-width: 0;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ -webkit-user-select: none;
+ user-select: none;
+ cursor: pointer;
+ z-index: 0;
+ min-width: 24px;
+ min-height: 24px;
+ width: 40px;
+ height: 40px;
+ padding: 8px;
+ font-weight: normal;
+ vertical-align: middle;
+ border: 0;
+ vertical-align: middle;
+ /* These are getting an outline in opera tv browsers, which run chrome 30 */
+ outline: none !important;
+ position: relative;
+ overflow: hidden;
+ font-weight: 500;
+ text-transform: uppercase;
+ border-radius: 50%;
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+ justify-content: center;
+}
+
+ [is=paper-icon-button-light].autoSize {
+ width: auto !important;
+ height: auto !important;
+ }
+
+ [is=paper-icon-button-light][disabled] {
+ opacity: .3;
+ }
+
+ [is=paper-icon-button-light] i {
+ width: 24px;
+ height: 24px;
+ font-size: 24px;
+ /* Make sure its on top of the ripple */
+ position: relative;
+ z-index: 1;
+ vertical-align: middle;
+ }
+
+.layout-tv [is=paper-icon-button-light] {
+ width: auto;
+ height: auto;
+ min-width: initial;
+ min-height: initial;
+}
+
+ .layout-tv [is=paper-icon-button-light] i {
+ width: 3.7vh;
+ height: 3.7vh;
+ font-size: 3.7vh;
+ }
+
+[is=paper-icon-button-light] iron-icon {
+ width: 100%;
+ height: 100%;
+ /* Make sure its on top of the ripple */
+ position: relative;
+ z-index: 1;
+ vertical-align: middle;
+}
+
+[is=paper-icon-button-light] img {
+ width: 100%;
+ /* Can't use 100% height or it will stretch past the boundaries in safari */
+ /*height: 100%;*/
+ max-height: 100%;
+ /* Make sure its on top of the ripple */
+ position: relative;
+ z-index: 1;
+ vertical-align: middle;
+}
+
+[is=paper-icon-button-light]:after {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ transition: opacity .3s ease-out;
+ background: currentcolor;
+ opacity: 0;
+}
+
+[is=paper-icon-button-light]:focus:after {
+ opacity: .2;
+}
+
+.ripple-effect {
+ position: absolute;
+ border-radius: 50%;
+ width: 50px;
+ height: 50px;
+ top: 50%;
+ left: 50%;
+ background: currentcolor;
+ animation: ripple-animation .8s;
+ opacity: 0.25;
+ -webkit-transform: translate(0, 0);
+ transform: translate3d(0, 0, 0);
+}
+
+@keyframes ripple-animation {
+ from {
+ transform: none;
+ opacity: 0.5;
+ }
+
+ to {
+ transform: scale(20);
+ opacity: 0;
+ }
+}
diff --git a/dashboard-ui/bower_components/emby-webcomponents/emby-button/emby-button.js b/dashboard-ui/bower_components/emby-webcomponents/emby-button/emby-button.js
new file mode 100644
index 0000000000..4d19858034
--- /dev/null
+++ b/dashboard-ui/bower_components/emby-webcomponents/emby-button/emby-button.js
@@ -0,0 +1,73 @@
+define(['browser', 'css!./emby-button', 'registerElement'], function (browser) {
+
+ var EmbyButtonPrototype = Object.create(HTMLButtonElement.prototype);
+
+ function animateButtonInternal(e, btn) {
+
+ var div = document.createElement('div');
+
+ div.classList.add('ripple-effect');
+
+ var offsetX = e.offsetX || 0;
+ var offsetY = e.offsetY || 0;
+
+ if (offsetX > 0 && offsetY > 0) {
+ div.style.left = offsetX + 'px';
+ div.style.top = offsetY + 'px';
+ }
+
+ btn.appendChild(div);
+
+ div.addEventListener("animationend", function () {
+ div.parentNode.removeChild(div);
+ }, false);
+ }
+
+ function animateButton(e) {
+
+ var btn = this;
+ requestAnimationFrame(function () {
+ animateButtonInternal(e, btn);
+ });
+ }
+
+ function onKeyDown(e) {
+
+ if (e.keyCode == 13) {
+ animateButton.call(this, e);
+ }
+ }
+
+ function onMouseDown(e) {
+
+ if (e.button == 0) {
+ animateButton.call(this, e);
+ }
+ }
+
+ EmbyButtonPrototype.attachedCallback = function () {
+
+ if (this.getAttribute('data-embybutton') == 'true') {
+ return;
+ }
+
+ this.setAttribute('data-embybutton', 'true');
+
+ if (browser.safari || browser.firefox || browser.noFlex) {
+ this.classList.add('noflex');
+ }
+
+ this.addEventListener('keydown', onKeyDown);
+ if (browser.safari) {
+ this.addEventListener('click', animateButton);
+ } else {
+ this.addEventListener('mousedown', onMouseDown);
+ //this.addEventListener('touchstart', animateButton);
+ }
+ };
+
+ document.registerElement('emby-button', {
+ prototype: EmbyButtonPrototype,
+ extends: 'button'
+ });
+});
\ No newline at end of file
diff --git a/dashboard-ui/bower_components/emby-webcomponents/emby-button/paper-icon-button-light.js b/dashboard-ui/bower_components/emby-webcomponents/emby-button/paper-icon-button-light.js
new file mode 100644
index 0000000000..3a9f18929d
--- /dev/null
+++ b/dashboard-ui/bower_components/emby-webcomponents/emby-button/paper-icon-button-light.js
@@ -0,0 +1,57 @@
+define(['css!./emby-button', 'registerElement'], function () {
+
+ var EmbyButtonPrototype = Object.create(HTMLButtonElement.prototype);
+
+ function animateButtonInternal(e, btn) {
+
+ var div = document.createElement('div');
+
+ div.classList.add('ripple-effect');
+
+ var offsetX = e.offsetX || 0;
+ var offsetY = e.offsetY || 0;
+
+ if (offsetX > 0 && offsetY > 0) {
+ div.style.left = offsetX + 'px';
+ div.style.top = offsetY + 'px';
+ }
+
+ btn.appendChild(div);
+
+ div.addEventListener("animationend", function () {
+ div.parentNode.removeChild(div);
+ }, false);
+ }
+
+ function animateButton(e) {
+
+ var btn = this;
+ requestAnimationFrame(function () {
+ animateButtonInternal(e, btn);
+ });
+ }
+
+ function onKeyDown(e) {
+
+ if (e.keyCode == 13) {
+ animateButton.call(this, e);
+ }
+ }
+
+ EmbyButtonPrototype.attachedCallback = function () {
+
+ if (this.getAttribute('data-embybutton') == 'true') {
+ return;
+ }
+
+ this.setAttribute('data-embybutton', 'true');
+
+ this.addEventListener('keydown', onKeyDown);
+ this.addEventListener('click', animateButton);
+ };
+
+ document.registerElement('paper-icon-button-light', {
+ prototype: EmbyButtonPrototype,
+ extends: 'button'
+ });
+});
\ No newline at end of file
diff --git a/dashboard-ui/bower_components/emby-webcomponents/emby-checkbox/emby-checkbox.css b/dashboard-ui/bower_components/emby-webcomponents/emby-checkbox/emby-checkbox.css
new file mode 100644
index 0000000000..967087a9b9
--- /dev/null
+++ b/dashboard-ui/bower_components/emby-webcomponents/emby-checkbox/emby-checkbox.css
@@ -0,0 +1,139 @@
+.mdl-checkbox {
+ position: relative;
+ z-index: 1;
+ vertical-align: middle;
+ display: inline-flex;
+ box-sizing: border-box;
+ width: 100%;
+ margin: 0;
+ padding: 0;
+ padding-left: 36px;
+ align-items: center;
+ height: 32px;
+}
+
+.checkboxFieldDescription {
+ padding-left: 36px;
+}
+
+.checkboxContainer {
+ margin-bottom: 2em;
+ display: flex;
+}
+
+div.checkboxContainer {
+ display: block;
+}
+
+.mdl-checkbox__input {
+ position: absolute;
+ width: 0;
+ height: 0;
+ margin: 0;
+ padding: 0;
+ opacity: 0;
+ -ms-appearance: none;
+ -moz-appearance: none;
+ -webkit-appearance: none;
+ appearance: none;
+ border: none;
+}
+
+.checkboxOutline {
+ position: absolute;
+ top: 3px;
+ left: 0;
+ display: inline-block;
+ box-sizing: border-box;
+ width: 24px;
+ height: 24px;
+ margin: 0;
+ cursor: pointer;
+ overflow: hidden;
+ border: 2px solid currentcolor;
+ border-radius: 2px;
+ z-index: 2;
+}
+
+.mdl-checkbox__input:checked + span + span + .checkboxOutline {
+ border-color: #52B54B;
+}
+
+.mdl-checkbox__input[disabled] + span + span + .checkboxOutline {
+ border-color: rgba(0, 0, 0, 0.26);
+ cursor: auto;
+}
+
+.mdl-checkbox__focus-helper {
+ position: absolute;
+ top: -12px;
+ left: -12px;
+ width: 48px;
+ height: 48px;
+ display: inline-block;
+ box-sizing: border-box;
+ margin: 3px 0 0 0;
+ border-radius: 50%;
+ background-color: transparent;
+}
+
+.mdl-checkbox__input:focus + span + .mdl-checkbox__focus-helper {
+ background-color: rgba(82, 181, 75, 0.26);
+}
+
+.mdl-checkbox__tick-outline {
+ position: absolute;
+ top: 0;
+ left: 0;
+ height: 100%;
+ width: 100%;
+ background: transparent;
+ transition-duration: 0.28s;
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
+ transition-property: background;
+}
+
+.mdl-checkbox__input:checked + span + span + .checkboxOutline .mdl-checkbox__tick-outline {
+ background: #52B54B url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgdmVyc2lvbj0iMS4xIgogICB2aWV3Qm94PSIwIDAgMSAxIgogICBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWluWU1pbiBtZWV0Ij4KICA8cGF0aAogICAgIGQ9Ik0gMC4wNDAzODA1OSwwLjYyNjc3NjcgMC4xNDY0NDY2MSwwLjUyMDcxMDY4IDAuNDI5Mjg5MzIsMC44MDM1NTMzOSAwLjMyMzIyMzMsMC45MDk2MTk0MSB6IE0gMC4yMTcxNTcyOSwwLjgwMzU1MzM5IDAuODUzNTUzMzksMC4xNjcxNTcyOSAwLjk1OTYxOTQxLDAuMjczMjIzMyAwLjMyMzIyMzMsMC45MDk2MTk0MSB6IgogICAgIGlkPSJyZWN0Mzc4MCIKICAgICBzdHlsZT0iZmlsbDojZmZmZmZmO2ZpbGwtb3BhY2l0eToxO3N0cm9rZTpub25lIiAvPgo8L3N2Zz4K");
+}
+
+.mdl-checkbox__input:checked[disabled] + span + span + .checkboxOutline .mdl-checkbox__tick-outline {
+ background: rgba(0, 0, 0, 0.26) url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgdmVyc2lvbj0iMS4xIgogICB2aWV3Qm94PSIwIDAgMSAxIgogICBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWluWU1pbiBtZWV0Ij4KICA8cGF0aAogICAgIGQ9Ik0gMC4wNDAzODA1OSwwLjYyNjc3NjcgMC4xNDY0NDY2MSwwLjUyMDcxMDY4IDAuNDI5Mjg5MzIsMC44MDM1NTMzOSAwLjMyMzIyMzMsMC45MDk2MTk0MSB6IE0gMC4yMTcxNTcyOSwwLjgwMzU1MzM5IDAuODUzNTUzMzksMC4xNjcxNTcyOSAwLjk1OTYxOTQxLDAuMjczMjIzMyAwLjMyMzIyMzMsMC45MDk2MTk0MSB6IgogICAgIGlkPSJyZWN0Mzc4MCIKICAgICBzdHlsZT0iZmlsbDojZmZmZmZmO2ZpbGwtb3BhY2l0eToxO3N0cm9rZTpub25lIiAvPgo8L3N2Zz4K");
+}
+
+.checkboxLabel {
+ position: relative;
+ cursor: pointer;
+ margin: 0;
+}
+
+.mdl-checkbox__input[disabled] + .checkboxLabel {
+ color: rgba(0, 0, 0, 0.26);
+ cursor: auto;
+}
+
+.checkboxList .mdl-checkbox {
+ display: flex;
+ margin: .5em 0;
+}
+
+.layout-tv .mdl-checkbox {
+ height: 4.6vh;
+ padding-left: 6vh;
+}
+
+.layout-tv .checkboxFieldDescription {
+ padding-left: 6vh;
+}
+
+.layout-tv .checkboxOutline {
+ width: 4.6vh;
+ height: 4.6vh;
+}
+
+.layout-tv .mdl-checkbox__focus-helper {
+ top: -3.7vh;
+ left: -3.7vh;
+ width: 12vh;
+ height: 12vh;
+}
diff --git a/dashboard-ui/bower_components/emby-webcomponents/emby-checkbox/emby-checkbox.js b/dashboard-ui/bower_components/emby-webcomponents/emby-checkbox/emby-checkbox.js
new file mode 100644
index 0000000000..e96eab2a36
--- /dev/null
+++ b/dashboard-ui/bower_components/emby-webcomponents/emby-checkbox/emby-checkbox.js
@@ -0,0 +1,45 @@
+define(['css!./emby-checkbox', 'registerElement'], function () {
+
+ var EmbyCheckboxPrototype = Object.create(HTMLInputElement.prototype);
+
+ function onKeyDown(e) {
+
+ // Don't submit form on enter
+ if (e.keyCode == 13) {
+ e.preventDefault();
+
+ this.checked = !this.checked;
+
+ return false;
+ }
+ }
+
+ EmbyCheckboxPrototype.attachedCallback = function () {
+
+ if (this.getAttribute('data-embycheckbox') == 'true') {
+ return;
+ }
+
+ this.setAttribute('data-embycheckbox', 'true');
+
+ this.classList.add('mdl-checkbox__input');
+
+ var labelElement = this.parentNode;
+ //labelElement.classList.add('mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect mdl-js-ripple-effect--ignore-events');
+ labelElement.classList.add('mdl-checkbox');
+ labelElement.classList.add('mdl-js-checkbox');
+ labelElement.classList.add('mdl-js-ripple-effect');
+
+ var labelTextElement = labelElement.querySelector('span');
+ labelElement.insertAdjacentHTML('beforeend', '
');
+
+ labelTextElement.classList.add('checkboxLabel');
+
+ this.addEventListener('keydown', onKeyDown);
+ };
+
+ document.registerElement('emby-checkbox', {
+ prototype: EmbyCheckboxPrototype,
+ extends: 'input'
+ });
+});
\ No newline at end of file
diff --git a/dashboard-ui/bower_components/emby-webcomponents/emby-input/emby-input.css b/dashboard-ui/bower_components/emby-webcomponents/emby-input/emby-input.css
new file mode 100644
index 0000000000..ec2feb3f81
--- /dev/null
+++ b/dashboard-ui/bower_components/emby-webcomponents/emby-input/emby-input.css
@@ -0,0 +1,59 @@
+[is="emby-input"] {
+ display: block;
+ margin: 0;
+ margin-bottom: 0 !important;
+ background: none;
+ border: 1px solid rgb(221, 221, 221);
+ border-width: 0 0 1px 0;
+ /* Prefixed box-sizing rules necessary for older browsers */
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ /* Remove select styling */
+ /* Font size must the 16px or larger to prevent iOS page zoom on focus */
+ font-size: inherit;
+ /* General select styles: change as needed */
+ font-family: inherit;
+ font-weight: inherit;
+ color: inherit;
+ padding: .35em 0 .3em 0;
+ cursor: pointer;
+ outline: none !important;
+ width: 100%;
+ background-color: transparent;
+ border-radius: 0;
+}
+
+.inputContainer {
+ margin-bottom: 2em;
+}
+
+.inputLabel {
+ display: inline-block;
+ transition: all .2s ease-out;
+}
+
+ .inputLabel.blank:not(.nofloat) {
+ transform-origin: left top;
+ transform: scale(1.4,1.4) translateY(80%);
+ }
+
+.inputLabel.focused:not(.blank) {
+ color: #52B54B;
+}
+
+.emby-input-selectionbar {
+ height: 2px;
+ transform: scale(.01, 1);
+ transition: transform .25s ease-out;
+ position: relative;
+ top: -1px;
+ margin-bottom: .5em;
+ -webkit-transform-origin: center center;
+ transform-origin: center center;
+}
+
+[is="emby-input"]:focus + .emby-input-selectionbar {
+ background-color: #52B54B;
+ transform: none;
+}
diff --git a/dashboard-ui/bower_components/emby-webcomponents/emby-input/emby-input.js b/dashboard-ui/bower_components/emby-webcomponents/emby-input/emby-input.js
new file mode 100644
index 0000000000..b96089afeb
--- /dev/null
+++ b/dashboard-ui/bower_components/emby-webcomponents/emby-input/emby-input.js
@@ -0,0 +1,93 @@
+define(['layoutManager', 'browser', 'css!./emby-input', 'registerElement'], function (layoutManager, browser) {
+
+ var EmbyInputPrototype = Object.create(HTMLInputElement.prototype);
+
+ var inputId = 0;
+ var supportsFloatingLabel = false;
+
+ if (Object.getOwnPropertyDescriptor && Object.defineProperty) {
+
+ var descriptor = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value');
+
+ // descriptor returning null in webos
+ if (descriptor && descriptor.configurable) {
+ var baseSetMethod = descriptor.set;
+ descriptor.set = function (value) {
+ baseSetMethod.call(this, value);
+
+ this.dispatchEvent(new CustomEvent('valueset', {
+ bubbles: false,
+ cancelable: false
+ }));
+ }
+
+ Object.defineProperty(HTMLInputElement.prototype, 'value', descriptor);
+ supportsFloatingLabel = true;
+ }
+ }
+
+ EmbyInputPrototype.createdCallback = function () {
+
+ if (!this.id) {
+ this.id = 'embyinput' + inputId;
+ inputId++;
+ }
+ };
+
+ EmbyInputPrototype.attachedCallback = function () {
+
+ if (this.getAttribute('data-embyinput') == 'true') {
+ return;
+ }
+
+ this.setAttribute('data-embyinput', 'true');
+
+ var parentNode = this.parentNode;
+ var label = this.ownerDocument.createElement('label');
+ label.innerHTML = this.getAttribute('label') || '';
+ label.classList.add('inputLabel');
+
+ if (!supportsFloatingLabel || this.type == 'date') {
+ label.classList.add('nofloat');
+ }
+
+ label.htmlFor = this.id;
+ parentNode.insertBefore(label, this);
+
+ var div = document.createElement('div');
+ div.classList.add('emby-input-selectionbar');
+ parentNode.insertBefore(div, this.nextSibling);
+
+ function onChange() {
+ if (this.value) {
+ label.classList.remove('blank');
+ } else {
+ label.classList.add('blank');
+ }
+ }
+
+ this.addEventListener('focus', function () {
+ onChange.call(this);
+ label.classList.add('focused');
+ });
+ this.addEventListener('blur', function () {
+ onChange.call(this);
+ label.classList.remove('focused');
+ });
+
+ this.addEventListener('change', onChange);
+ this.addEventListener('input', onChange);
+ this.addEventListener('valueset', onChange);
+
+ onChange.call(this);
+
+ this.label = function (text) {
+ label.innerHTML = text;
+ };
+ };
+
+ document.registerElement('emby-input', {
+ prototype: EmbyInputPrototype,
+ extends: 'input'
+ });
+});
\ No newline at end of file
diff --git a/dashboard-ui/bower_components/emby-webcomponents/emby-select/emby-select.css b/dashboard-ui/bower_components/emby-webcomponents/emby-select/emby-select.css
new file mode 100644
index 0000000000..8045e5327f
--- /dev/null
+++ b/dashboard-ui/bower_components/emby-webcomponents/emby-select/emby-select.css
@@ -0,0 +1,55 @@
+[is="emby-select"] {
+ display: block;
+ margin: 0;
+ margin-bottom: 0 !important;
+ background: none;
+ border: 1px solid rgb(221, 221, 221);
+ border-width: 0 0 1px 0;
+ /* Prefixed box-sizing rules necessary for older browsers */
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ /* Remove select styling */
+ /* Font size must the 16px or larger to prevent iOS page zoom on focus */
+ font-size: inherit;
+ /* General select styles: change as needed */
+ font-family: inherit;
+ font-weight: inherit;
+ color: inherit;
+ padding: .35em .8em .3em 0;
+ cursor: pointer;
+ outline: none !important;
+ width: 100%;
+}
+
+[is="emby-select"] option {
+ color: initial;
+}
+
+.selectContainer {
+ margin-bottom: 2em;
+}
+
+.selectLabel {
+ display: block;
+}
+
+.selectLabelFocused {
+ color: #52B54B;
+}
+
+.emby-select-selectionbar {
+ height: 2px;
+ transform: scale(.01, 1);
+ transition: transform .25s ease-out;
+ position: relative;
+ top: -1px;
+ margin-bottom: .5em;
+ -webkit-transform-origin: center center;
+ transform-origin: center center;
+}
+
+[is="emby-select"]:focus + .emby-select-selectionbar {
+ background-color: #52B54B;
+ transform: none;
+}
diff --git a/dashboard-ui/bower_components/emby-webcomponents/emby-select/emby-select.js b/dashboard-ui/bower_components/emby-webcomponents/emby-select/emby-select.js
new file mode 100644
index 0000000000..88348b86cc
--- /dev/null
+++ b/dashboard-ui/bower_components/emby-webcomponents/emby-select/emby-select.js
@@ -0,0 +1,156 @@
+define(['layoutManager', 'browser', 'actionsheet', 'css!./emby-select', 'registerElement'], function (layoutManager, browser, actionsheet) {
+
+ var EmbySelectPrototype = Object.create(HTMLSelectElement.prototype);
+
+ function enableNativeMenu() {
+
+ if (browser.xboxOne) {
+ return false;
+ }
+
+ // Take advantage of the native input methods
+ if (browser.tv) {
+ return true;
+ }
+
+ if (layoutManager.tv) {
+ return false;
+ }
+
+ return true;
+ }
+
+ function triggerChange(select) {
+ var evt = document.createEvent("HTMLEvents");
+ evt.initEvent("change", false, true);
+ select.dispatchEvent(evt);
+ }
+
+ function setValue(select, value) {
+
+ select.value = value;
+ }
+
+ function showActionSheeet(select) {
+
+ var labelElem = getLabel(select);
+ var title = labelElem ? (labelElem.textContent || labelElem.innerText) : null;
+
+ actionsheet.show({
+ items: select.options,
+ positionTo: select,
+ title: title
+
+ }).then(function (value) {
+ setValue(select, value);
+ triggerChange(select);
+ });
+ }
+
+ function getLabel(select) {
+ var elem = select.previousSibling;
+ while (elem && elem.tagName != 'LABEL') {
+ elem = elem.previousSibling;
+ }
+ return elem;
+ }
+
+ function onFocus(e) {
+ var label = getLabel(this);
+ if (label) {
+ label.classList.add('selectLabelFocused');
+ label.classList.remove('selectLabelUnfocused');
+ }
+ }
+
+ function onBlur(e) {
+ var label = getLabel(this);
+ if (label) {
+ label.classList.add('selectLabelUnfocused');
+ label.classList.remove('selectLabelFocused');
+ }
+ }
+
+ function onMouseDown(e) {
+
+ // e.button=0 for primary (left) mouse button click
+ if (!e.button && !enableNativeMenu()) {
+ e.preventDefault();
+ showActionSheeet(this);
+ }
+ }
+
+ function onKeyDown(e) {
+
+ switch (e.keyCode) {
+
+ case 13:
+ if (!enableNativeMenu()) {
+ e.preventDefault();
+ showActionSheeet(this);
+ }
+ return;
+ case 37:
+ case 38:
+ case 39:
+ case 40:
+ if (layoutManager.tv) {
+ e.preventDefault();
+ }
+ return;
+ default:
+ break;
+ }
+ }
+
+ var inputId = 0;
+
+ EmbySelectPrototype.createdCallback = function () {
+
+ var parent = this.parentNode;
+ if (!parent.classList.contains('selectContainer')) {
+ var div = this.ownerDocument.createElement('div');
+ div.classList.add('selectContainer');
+ parent.replaceChild(div, this);
+ div.appendChild(this);
+ }
+
+ if (!this.id) {
+ this.id = 'embyselect' + inputId;
+ inputId++;
+ }
+
+ this.removeEventListener('mousedown', onMouseDown);
+ this.removeEventListener('keydown', onKeyDown);
+ this.removeEventListener('focus', onFocus);
+ this.removeEventListener('blur', onBlur);
+
+ this.addEventListener('mousedown', onMouseDown);
+ this.addEventListener('keydown', onKeyDown);
+ this.addEventListener('focus', onFocus);
+ this.addEventListener('blur', onBlur);
+ };
+
+ EmbySelectPrototype.attachedCallback = function () {
+
+ if (this.getAttribute('data-embyselect') != 'true') {
+ this.setAttribute('data-embyselect', 'true');
+
+ var label = this.ownerDocument.createElement('label');
+ label.innerHTML = this.getAttribute('label') || '';
+ label.classList.add('selectLabel');
+ label.classList.add('selectLabelUnfocused');
+ label.htmlFor = this.id;
+ this.parentNode.insertBefore(label, this);
+
+ var div = document.createElement('div');
+ div.classList.add('emby-select-selectionbar');
+ this.parentNode.insertBefore(div, this.nextSibling);
+ }
+ };
+
+ document.registerElement('emby-select', {
+ prototype: EmbySelectPrototype,
+ extends: 'select'
+ });
+});
\ No newline at end of file
diff --git a/dashboard-ui/bower_components/emby-webcomponents/emby-slider/emby-slider.css b/dashboard-ui/bower_components/emby-webcomponents/emby-slider/emby-slider.css
new file mode 100644
index 0000000000..ccbb2325f4
--- /dev/null
+++ b/dashboard-ui/bower_components/emby-webcomponents/emby-slider/emby-slider.css
@@ -0,0 +1,338 @@
+_:-ms-input-placeholder, :root .mdl-slider.mdl-slider {
+ -ms-appearance: none;
+ height: 32px;
+ margin: 0;
+}
+
+.mdl-slider {
+ width: 100%;
+}
+
+.mdl-slider {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ height: 2px;
+ background: transparent;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ outline: 0;
+ padding: 0;
+ color: #52B54B;
+ -webkit-align-self: center;
+ -ms-flex-item-align: center;
+ align-self: center;
+ z-index: 1;
+ cursor: pointer;
+ margin: 0;
+ /**************************** Tracks ****************************/
+ /**************************** Thumbs ****************************/
+ /**************************** 0-value ****************************/
+ /**************************** Disabled ****************************/
+}
+
+.layout-tv .mdl-slider {
+ height: .56vh;
+}
+
+.mdl-slider::-moz-focus-outer {
+ border: 0;
+}
+
+.mdl-slider::-ms-tooltip {
+ display: none;
+}
+
+.mdl-slider::-webkit-slider-runnable-track {
+ background: transparent;
+}
+
+.mdl-slider::-moz-range-track {
+ background: #666;
+ border: none;
+}
+
+.mdl-slider::-moz-range-progress {
+ background: #52B54B;
+}
+
+.mdl-slider::-ms-track {
+ background: none;
+ color: transparent;
+ height: 2px;
+ width: 100%;
+ border: none;
+}
+
+.layout-tv .mdl-slider::-ms-track {
+ height: .56vh;
+}
+
+.mdl-slider::-ms-fill-lower {
+ padding: 0;
+ background: linear-gradient(to right, transparent, transparent 16px, #52B54B 16px, #52B54B 0);
+}
+
+.mdl-slider::-ms-fill-upper {
+ padding: 0;
+ background: linear-gradient(to left, transparent, transparent 16px, #666 16px, #666 0);
+}
+
+.mdl-slider::-webkit-slider-thumb {
+ -webkit-appearance: none;
+ width: 16px;
+ height: 16px;
+ box-sizing: border-box;
+ border-radius: 50%;
+ background: #52B54B;
+ border: none;
+ transition: border 0.18s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.18s cubic-bezier(0.4, 0, 0.2, 1), background 0.28s cubic-bezier(0.4, 0, 0.2, 1), -webkit-transform 0.18s cubic-bezier(0.4, 0, 0.2, 1);
+ transition: transform 0.18s cubic-bezier(0.4, 0, 0.2, 1), border 0.18s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.18s cubic-bezier(0.4, 0, 0.2, 1), background 0.28s cubic-bezier(0.4, 0, 0.2, 1);
+ transition: transform 0.18s cubic-bezier(0.4, 0, 0.2, 1), border 0.18s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.18s cubic-bezier(0.4, 0, 0.2, 1), background 0.28s cubic-bezier(0.4, 0, 0.2, 1), -webkit-transform 0.18s cubic-bezier(0.4, 0, 0.2, 1);
+}
+
+.layout-tv .mdl-slider::-webkit-slider-thumb {
+ width: 2vh;
+ height: 2vh;
+}
+
+.mdl-slider::-moz-range-thumb {
+ -moz-appearance: none;
+ width: 16px;
+ height: 16px;
+ box-sizing: border-box;
+ border-radius: 50%;
+ background-image: none;
+ background: #52B54B;
+ border: none;
+}
+
+.layout-tv .mdl-slider::-moz-range-thumb {
+ width: 2vh;
+ height: 2vh;
+}
+
+.mdl-slider:focus:not(:active)::-webkit-slider-thumb {
+ box-shadow: 0 0 0 10px rgba(82, 181, 75, 0.26);
+}
+
+.mdl-slider:focus:not(:active)::-moz-range-thumb {
+ box-shadow: 0 0 0 10px rgba(82, 181, 75, 0.26);
+}
+
+.mdl-slider:active::-webkit-slider-thumb {
+ background-image: none;
+ background: #52B54B;
+ -webkit-transform: scale(1.5);
+ transform: scale(1.5);
+}
+
+.mdl-slider:active::-moz-range-thumb {
+ background-image: none;
+ background: #52B54B;
+ transform: scale(1.5);
+}
+
+.mdl-slider::-ms-thumb {
+ width: 16px;
+ height: 16px;
+ border: none;
+ border-radius: 50%;
+ background: #52B54B;
+}
+
+.mdl-slider[disabled]::-ms-thumb {
+ background: gray;
+}
+
+.layout-tv .mdl-slider::-ms-thumb {
+ width: 2vh;
+ height: 2vh;
+}
+
+.layout-tv .mdl-slider::-webkit-slider-thumb {
+ display: none;
+}
+
+.layout-tv .mdl-slider:hover::-webkit-slider-thumb {
+ display: block;
+}
+
+.mdl-slider.is-lowest-value::-webkit-slider-thumb {
+ /*border: 2px solid #52B54B;
+ background: transparent;*/
+}
+
+.mdl-slider.is-lowest-value::-moz-range-thumb {
+ /*border: 2px solid #52B54B;
+ background: transparent;*/
+}
+
+.mdl-slider.is-lowest-value + .mdl-slider__background-flex > .mdl-slider__background-upper {
+ left: 6px;
+}
+
+.mdl-slider.is-lowest-value:focus:not(:active)::-webkit-slider-thumb {
+ /*box-shadow: 0 0 0 10px rgba(0,0,0, 0.12);
+ background: rgba(0,0,0, 0.12);*/
+}
+
+.mdl-slider.is-lowest-value:focus:not(:active)::-moz-range-thumb {
+ /*box-shadow: 0 0 0 10px rgba(0,0,0, 0.12);
+ background: rgba(0,0,0, 0.12);*/
+}
+
+.mdl-slider.is-lowest-value:active::-webkit-slider-thumb {
+ border: 1.6px solid #52B54B;
+ -webkit-transform: scale(1.5);
+ transform: scale(1.5);
+}
+
+.mdl-slider.is-lowest-value:active + .mdl-slider__background-flex > .mdl-slider__background-upper {
+ left: 9px;
+}
+
+.mdl-slider.is-lowest-value:active::-moz-range-thumb {
+ border: 1.5px solid #52B54B;
+ transform: scale(1.5);
+}
+
+.mdl-slider.is-lowest-value::-ms-fill-lower {
+ background: transparent;
+}
+
+.mdl-slider.is-lowest-value::-ms-fill-upper {
+ margin-left: 6px;
+}
+
+.mdl-slider.is-lowest-value:active::-ms-fill-upper {
+ margin-left: 9px;
+}
+
+.mdl-slider:disabled:focus::-webkit-slider-thumb, .mdl-slider:disabled:active::-webkit-slider-thumb, .mdl-slider:disabled::-webkit-slider-thumb {
+ -webkit-transform: scale(0.667);
+ transform: scale(0.667);
+ background: rgba(0,0,0, 0.26);
+}
+
+.mdl-slider:disabled:focus::-moz-range-thumb, .mdl-slider:disabled:active::-moz-range-thumb, .mdl-slider:disabled::-moz-range-thumb {
+ transform: scale(0.667);
+ background: rgba(0,0,0, 0.26);
+}
+
+.mdl-slider:disabled + .mdl-slider__background-flex > .mdl-slider__background-lower {
+ background-color: #666;
+ left: -6px;
+}
+
+.mdl-slider:disabled + .mdl-slider__background-flex > .mdl-slider__background-upper {
+ left: 6px;
+}
+
+.mdl-slider.is-lowest-value:disabled:focus::-webkit-slider-thumb, .mdl-slider.is-lowest-value:disabled:active::-webkit-slider-thumb, .mdl-slider.is-lowest-value:disabled::-webkit-slider-thumb {
+ border: 3px solid rgba(0,0,0, 0.26);
+ background: transparent;
+ -webkit-transform: scale(0.667);
+ transform: scale(0.667);
+}
+
+.mdl-slider.is-lowest-value:disabled:focus::-moz-range-thumb, .mdl-slider.is-lowest-value:disabled:active::-moz-range-thumb, .mdl-slider.is-lowest-value:disabled::-moz-range-thumb {
+ border: 3px solid rgba(0,0,0, 0.26);
+ background: transparent;
+ transform: scale(0.667);
+}
+
+.mdl-slider.is-lowest-value:disabled:active + .mdl-slider__background-flex > .mdl-slider__background-upper {
+ left: 6px;
+}
+
+.mdl-slider:disabled::-ms-fill-lower {
+ margin-right: 6px;
+ background: linear-gradient(to right, transparent, transparent 25px, rgba(30,30,30, 0.7) 25px, rgba(30,30,30, 0.7) 0);
+}
+
+.mdl-slider:disabled::-ms-fill-upper {
+ margin-left: 6px;
+}
+
+.mdl-slider.is-lowest-value:disabled:active::-ms-fill-upper {
+ margin-left: 6px;
+}
+
+.mdl-slider__ie-container {
+ height: 18px;
+ overflow: visible;
+ border: none;
+ margin: none;
+ padding: none;
+}
+
+.mdl-slider__container {
+ height: 18px;
+ position: relative;
+ background: none;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-flex-direction: row;
+ -ms-flex-direction: row;
+ flex-direction: row;
+}
+
+.mdl-slider__background-flex {
+ background: transparent;
+ position: absolute;
+ height: 2px;
+ width: 100%;
+ top: 50%;
+ left: 0;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ overflow: hidden;
+ border: 0;
+ padding: 0;
+ -webkit-transform: translate(0, -1px);
+ transform: translate(0, -1px);
+}
+
+.layout-tv .mdl-slider__background-flex {
+ height: .56vh;
+}
+
+.mdl-slider__background-lower {
+ background: #52B54B;
+ -webkit-flex: 0;
+ -ms-flex: 0;
+ flex: 0;
+ position: relative;
+ border: 0;
+ padding: 0;
+}
+
+.mdl-slider__background-upper {
+ background: #666;
+ -webkit-flex: 0;
+ -ms-flex: 0;
+ flex: 0;
+ position: relative;
+ border: 0;
+ padding: 0;
+ transition: left 0.18s cubic-bezier(0.4, 0, 0.2, 1);
+}
+
+.sliderBubble {
+ position: absolute;
+ top: -3.7em;
+ left: 0;
+ padding: .75em;
+ background: #3367d6;
+ color: #fff;
+ border-radius: 1000px;
+ font-size: 90%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
diff --git a/dashboard-ui/bower_components/emby-webcomponents/emby-slider/emby-slider.js b/dashboard-ui/bower_components/emby-webcomponents/emby-slider/emby-slider.js
new file mode 100644
index 0000000000..20a21c28ca
--- /dev/null
+++ b/dashboard-ui/bower_components/emby-webcomponents/emby-slider/emby-slider.js
@@ -0,0 +1,120 @@
+define(['browser', 'css!./emby-slider', 'registerElement', 'emby-input'], function (browser) {
+
+ var EmbySliderPrototype = Object.create(HTMLInputElement.prototype);
+
+ var supportsNativeProgressStyle = browser.firefox || browser.edge || browser.msie;
+ var supportsValueSetOverride = false;
+
+ if (Object.getOwnPropertyDescriptor && Object.defineProperty) {
+
+ var descriptor = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value');
+ // descriptor returning null in webos
+ if (descriptor && descriptor.configurable) {
+ supportsValueSetOverride = true;
+ }
+ }
+
+ function updateValues(range, backgroundLower, backgroundUpper) {
+
+ //if (fraction === 0) {
+ // range.classList.add('is-lowest-value');
+ //} else {
+ // range.classList.remove('is-lowest-value');
+ //}
+
+ if (backgroundLower) {
+ var fraction = (range.value - range.min) / (range.max - range.min);
+
+ backgroundLower.style.flex = fraction;
+ backgroundLower.style.webkitFlex = fraction;
+ backgroundUpper.style.flex = 1 - fraction;
+ backgroundUpper.style.webkitFlex = 1 - fraction;
+ }
+ }
+
+ function updateBubble(range, bubble) {
+
+ var value = range.value;
+ bubble.style.left = (value - 1) + '%';
+
+ if (range.getBubbleText) {
+ value = range.getBubbleText(value);
+ }
+ bubble.innerHTML = value;
+ }
+
+ EmbySliderPrototype.attachedCallback = function () {
+
+ if (this.getAttribute('data-embycheckbox') == 'true') {
+ return;
+ }
+
+ this.setAttribute('data-embycheckbox', 'true');
+
+ this.classList.add('mdl-slider');
+ this.classList.add('mdl-js-slider');
+
+ var containerElement = this.parentNode;
+ containerElement.classList.add('mdl-slider__container');
+
+ var htmlToInsert = '';
+
+ if (!supportsNativeProgressStyle) {
+ htmlToInsert += '
';
+ }
+
+ htmlToInsert += '
';
+
+ containerElement.insertAdjacentHTML('beforeend', htmlToInsert);
+
+ var backgroundLower = containerElement.querySelector('.mdl-slider__background-lower');
+ var backgroundUpper = containerElement.querySelector('.mdl-slider__background-upper');
+ var sliderBubble = containerElement.querySelector('.sliderBubble');
+
+ this.addEventListener('input', function (e) {
+ this.dragging = true;
+ updateBubble(this, sliderBubble);
+ sliderBubble.classList.remove('hide');
+ });
+ this.addEventListener('change', function () {
+ this.dragging = false;
+ updateValues(this, backgroundLower, backgroundUpper);
+ sliderBubble.classList.add('hide');
+ });
+
+ if (!supportsNativeProgressStyle) {
+
+ if (supportsValueSetOverride) {
+ this.addEventListener('valueset', function () {
+ updateValues(this, backgroundLower, backgroundUpper);
+ });
+ } else {
+ startInterval(this, backgroundLower, backgroundUpper);
+ }
+ }
+ };
+
+ function startInterval(range, backgroundLower, backgroundUpper) {
+ var interval = range.interval;
+ if (interval) {
+ clearInterval(interval);
+ }
+ range.interval = setInterval(function () {
+ updateValues(range, backgroundLower, backgroundUpper);
+ }, 100);
+ }
+
+ EmbySliderPrototype.detachedCallback = function () {
+
+ var interval = this.interval;
+ if (interval) {
+ clearInterval(interval);
+ }
+ this.interval = null;
+ };
+
+ document.registerElement('emby-slider', {
+ prototype: EmbySliderPrototype,
+ extends: 'input'
+ });
+});
\ No newline at end of file
diff --git a/dashboard-ui/bower_components/emby-webcomponents/focusmanager.js b/dashboard-ui/bower_components/emby-webcomponents/focusmanager.js
index 6bf5e4a1c9..a2b2513f68 100644
--- a/dashboard-ui/bower_components/emby-webcomponents/focusmanager.js
+++ b/dashboard-ui/bower_components/emby-webcomponents/focusmanager.js
@@ -20,11 +20,6 @@ define([], function () {
function focus(element) {
- var tagName = element.tagName;
- if (tagName == 'PAPER-INPUT' || tagName == 'EMBY-DROPDOWN-MENU') {
- element = element.querySelector('input') || element;
- }
-
try {
element.focus();
} catch (err) {
@@ -32,7 +27,7 @@ define([], function () {
}
}
- var focusableTagNames = ['INPUT', 'TEXTAREA', 'SELECT', 'BUTTON', 'A', 'PAPER-BUTTON', 'PAPER-INPUT', 'PAPER-TEXTAREA', 'PAPER-FAB', 'PAPER-CHECKBOX', 'PAPER-ICON-ITEM', 'PAPER-MENU-ITEM', 'EMBY-DROPDOWN-MENU'];
+ var focusableTagNames = ['INPUT', 'TEXTAREA', 'SELECT', 'BUTTON', 'A', 'PAPER-CHECKBOX'];
var focusableContainerTagNames = ['BODY', 'DIALOG'];
var focusableQuery = focusableTagNames.join(',') + ',.focusable';
@@ -340,89 +335,62 @@ define([], function () {
var distX;
var distY;
- var distX2;
- var distY2;
switch (direction) {
case 0:
// left
- distX = distX2 = Math.abs(point1x - Math.min(point1x, x2));
+ distX = Math.abs(point1x - Math.min(point1x, x2));
distY = intersectY ? 0 : Math.abs(sourceMidY - midY);
- distY2 = Math.abs(sourceMidY - midY);
break;
case 1:
// right
- distX = distX2 = Math.abs(point2x - Math.max(point2x, x));
+ distX = Math.abs(point2x - Math.max(point2x, x));
distY = intersectY ? 0 : Math.abs(sourceMidY - midY);
- distY2 = Math.abs(sourceMidY - midY);
break;
case 2:
// up
- distY = distY2 = Math.abs(point1y - Math.min(point1y, y2));
+ distY = Math.abs(point1y - Math.min(point1y, y2));
distX = intersectX ? 0 : Math.abs(sourceMidX - midX);
- distX2 = Math.abs(sourceMidX - midX);
break;
case 3:
// down
- distY = distY2 = Math.abs(point2y - Math.max(point2y, y));
+ distY = Math.abs(point2y - Math.max(point2y, y));
distX = intersectX ? 0 : Math.abs(sourceMidX - midX);
- distX2 = Math.abs(sourceMidX - midX);
break;
default:
break;
}
var distT = Math.sqrt(distX * distX + distY * distY);
- var distT2 = Math.sqrt(distX2 * distX2 + distY2 * distY2);
cache.push({
node: elem,
distX: distX,
distY: distY,
distT: distT,
- distT2: distT2
+ index: i
});
}
cache.sort(sortNodesT);
- //if (direction >= 2) {
- // cache.sort(sortNodesX);
- //} else {
- // cache.sort(sortNodesY);
- //}
return cache;
}
- function sortNodesX(a, b) {
- var result = a.distX - b.distX;
-
- if (result == 0) {
- return a.distT - b.distT;
- }
-
- return result;
- }
-
function sortNodesT(a, b) {
+
var result = a.distT - b.distT;
-
- if (result == 0) {
- return a.distT2 - b.distT2;
+ if (result != 0) {
+ return result;
}
- return result;
- }
-
- function sortNodesY(a, b) {
- var result = a.distY - b.distY;
-
- if (result == 0) {
- return a.distT - b.distT;
+ result = a.index - b.index;
+ if (result != 0) {
+ return result;
}
- return result;
+ return 0;
}
function sendText(text) {
diff --git a/dashboard-ui/bower_components/emby-webcomponents/fonts/material-icons/style.css b/dashboard-ui/bower_components/emby-webcomponents/fonts/material-icons/style.css
index 5e998e2ec5..2c84045d3d 100644
--- a/dashboard-ui/bower_components/emby-webcomponents/fonts/material-icons/style.css
+++ b/dashboard-ui/bower_components/emby-webcomponents/fonts/material-icons/style.css
@@ -1,20 +1,25 @@
@font-face {
- font-family: 'Material Icons';
- font-style: normal;
- font-weight: 400;
- src: local('Material Icons'), local('MaterialIcons-Regular'), url(2fcrYFNaTjcS6g4U3t-Y5ZjZjT5FdEJ140U2DJYC3mY.woff2) format('woff2'), url(2fcrYFNaTjcS6g4U3t-Y5ewrjPiaoEww8AihgqWRJAo.woff) format('woff');
+ font-family: 'Material Icons';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Material Icons'), local('MaterialIcons-Regular'), url(2fcrYFNaTjcS6g4U3t-Y5ZjZjT5FdEJ140U2DJYC3mY.woff2) format('woff2'), url(2fcrYFNaTjcS6g4U3t-Y5ewrjPiaoEww8AihgqWRJAo.woff) format('woff');
}
-.material-icons {
- font-family: 'Material Icons';
- font-weight: normal;
- font-style: normal;
- letter-spacing: normal;
- text-transform: none;
- display: inline-block;
- white-space: nowrap;
- word-wrap: normal;
- direction: ltr;
- -webkit-font-feature-settings: 'liga';
- -webkit-font-smoothing: antialiased;
-}
\ No newline at end of file
+.md-icon {
+ font-family: 'Material Icons';
+ font-weight: normal;
+ font-style: normal;
+ letter-spacing: normal;
+ text-transform: none;
+ display: inline-block;
+ white-space: nowrap;
+ word-wrap: normal;
+ direction: ltr;
+ -webkit-font-feature-settings: 'liga';
+ -webkit-font-smoothing: antialiased;
+ text-rendering: optimizeLegibility;
+ font-feature-settings: "liga" 1;
+ line-height: 1;
+ overflow: hidden;
+ vertical-align: middle;
+}
diff --git a/dashboard-ui/bower_components/emby-webcomponents/formdialog.css b/dashboard-ui/bower_components/emby-webcomponents/formdialog.css
index 9d4555836e..893493234d 100644
--- a/dashboard-ui/bower_components/emby-webcomponents/formdialog.css
+++ b/dashboard-ui/bower_components/emby-webcomponents/formdialog.css
@@ -25,6 +25,7 @@
.formDialog .dialogContentInner {
padding-bottom: 10vh;
+ padding-top: .5em;
}
.layout-tv .formDialog .dialogContentInner {
@@ -32,7 +33,7 @@
}
.formDialog .centeredContent {
- max-width: 700px;
+ max-width: 740px;
}
.formDialog .dialogContentTitle {
@@ -46,13 +47,6 @@
}
}
-@media all and (max-height: 1400px) {
-
- .itemOverview {
- display: none;
- }
-}
-
.layout-tv .formDialog .dialogHeader {
padding-top: 1.5em;
padding-bottom: 1.5em;
diff --git a/dashboard-ui/bower_components/emby-webcomponents/guide/guide.css b/dashboard-ui/bower_components/emby-webcomponents/guide/guide.css
index eb9d3121b2..55126eb6d6 100644
--- a/dashboard-ui/bower_components/emby-webcomponents/guide/guide.css
+++ b/dashboard-ui/bower_components/emby-webcomponents/guide/guide.css
@@ -105,6 +105,47 @@
position: relative;
}
+.timeslotHeadersInner {
+ position: relative;
+}
+
+.currentTimeIndicatorBar {
+ position: absolute;
+ bottom: .05em;
+ left: 0;
+ width: 100%;
+ height: 2px;
+ display: flex;
+ margin-left: .65vh;
+ background-color: #52B54B;
+ height: 2px;
+ transform-origin: left;
+ transition: transform 500ms ease-out;
+}
+
+.currentTimeIndicatorArrowContainer {
+ position: absolute;
+ bottom: -1.3vh;
+ width: 100%;
+ color: #52B54B;
+ margin-left: .65vh;
+ transform-origin: left;
+ transition: transform 500ms ease-out;
+}
+
+.layout-tv .currentTimeIndicatorBar, .layout-tv .currentTimeIndicatorArrowContainer {
+ /* Need to account for the scrollbar not being there */
+ left: 4px;
+}
+
+.currentTimeIndicatorArrow {
+ width: 4vh;
+ height: 4vh;
+ font-size: 4vh;
+ color: #52B54B;
+ margin-left: -2vh;
+}
+
.channelPrograms, .timeslotHeadersInner {
width: 1800vw;
}
@@ -148,6 +189,7 @@
text-decoration: none;
/* Needed in firefox */
text-align: left;
+ contain: strict;
}
@media all and (min-width: 500px) {
@@ -185,7 +227,7 @@
.channelHeaderCell {
border-bottom: .65vh solid #121212 !important;
- background-size: auto 65.7%;
+ background-size: auto 70%;
background-position: 90% center;
background-repeat: no-repeat;
}
@@ -201,7 +243,7 @@
}
}
-@media all and (max-width: 1280px) {
+@media all and (max-width: 1200px) {
.channelHeaderCell.withImage .guideChannelNumber {
display: none;
@@ -233,7 +275,7 @@
}
.layout-tv .channelPrograms, .layout-tv .channelHeaderCell {
- height: 7.6vh;
+ height: 9vh;
}
}
@@ -300,6 +342,7 @@
align-items: center;
/* Needed for Firefox */
text-align: left;
+ contain: strict;
}
.timeslotCellInner {
@@ -324,16 +367,17 @@
color: #bbb;
}
-.programCell iron-icon {
+.programCell i {
margin-left: auto;
margin-right: .5em;
height: 3.5vh;
width: 3.5vh;
+ font-size: 3.5vh;
color: #ddd;
flex-shrink: 0;
}
- .programCell iron-icon + iron-icon {
+ .programCell i + i {
margin-left: .25em;
}
@@ -347,14 +391,21 @@
.guideChannelName {
margin-left: auto;
margin-right: 1em;
- max-width: 40%;
text-overflow: ellipsis;
overflow: hidden;
+ max-width: 70%;
+}
+
+@media all and (min-width: 1000px) {
+
+ .guideChannelName {
+ max-width: 40%;
+ }
}
@media all and (max-width: 1000px) {
- .guideChannelName {
+ .guideChannelNumber {
display: none;
}
}
@@ -363,13 +414,12 @@
height: auto !important;
}
-.programCell:focus, .channelHeaderCell:focus, .btnSelectDate:focus {
- background-color: #52B54B;
+.programCell, .channelHeaderCell, .btnSelectDate {
outline: none !important;
}
- .programCell:focus .programAccent {
- background-color: transparent !important;
+ .programCell:focus, .channelHeaderCell:focus, .btnSelectDate:focus {
+ background-color: #555;
}
.timerIcon, .seriesTimerIcon {
diff --git a/dashboard-ui/bower_components/emby-webcomponents/guide/guide.js b/dashboard-ui/bower_components/emby-webcomponents/guide/guide.js
index d4e40f5952..0217380ff7 100644
--- a/dashboard-ui/bower_components/emby-webcomponents/guide/guide.js
+++ b/dashboard-ui/bower_components/emby-webcomponents/guide/guide.js
@@ -1,25 +1,17 @@
-define(['require', 'browser', 'globalize', 'connectionManager', 'loading', 'scrollHelper', 'datetime', 'focusManager', 'imageLoader', 'events', 'layoutManager', 'itemShortcuts', 'registrationservices', 'clearButtonStyle', 'css!./guide.css', 'html!./../icons/mediainfo.html', 'html!./../icons/nav.html', 'scrollStyles'], function (require, browser, globalize, connectionManager, loading, scrollHelper, datetime, focusManager, imageLoader, events, layoutManager, itemShortcuts, registrationServices) {
+define(['require', 'browser', 'globalize', 'connectionManager', 'serverNotifications', 'loading', 'scrollHelper', 'datetime', 'focusManager', 'imageLoader', 'events', 'layoutManager', 'itemShortcuts', 'registrationservices', 'clearButtonStyle', 'css!./guide.css', 'material-icons', 'scrollStyles', 'emby-button'], function (require, browser, globalize, connectionManager, serverNotifications, loading, scrollHelper, datetime, focusManager, imageLoader, events, layoutManager, itemShortcuts, registrationServices) {
function Guide(options) {
var self = this;
var items = {};
- self.refresh = function () {
- reloadPage(options.element);
- };
-
- self.destroy = function () {
- itemShortcuts.off(options.element);
- items = {};
- };
-
self.options = options;
// 30 mins
var cellCurationMinutes = 30;
var cellDurationMs = cellCurationMinutes * 60 * 1000;
var msPerDay = 86400000;
+ var totalRendererdMs = msPerDay;
var currentDate;
@@ -31,6 +23,24 @@
var channelsPromise;
+ self.refresh = function () {
+
+ currentDate = null;
+ reloadPage(options.element);
+ };
+
+ self.destroy = function () {
+
+ events.off(serverNotifications, 'TimerCreated', onTimerCreated);
+ events.off(serverNotifications, 'SeriesTimerCreated', onSeriesTimerCreated);
+ events.off(serverNotifications, 'TimerCancelled', onTimerCancelled);
+ events.off(serverNotifications, 'SeriesTimerCancelled', onSeriesTimerCancelled);
+
+ clearCurrentTimeUpdateInterval();
+ itemShortcuts.off(options.element);
+ items = {};
+ };
+
function normalizeDateToTimeslot(date) {
var minutesOffset = date.getMinutes() - cellCurationMinutes;
@@ -55,6 +65,55 @@
loading.hide();
}
+ var currentTimeUpdateInterval;
+ var currentTimeIndicatorBar;
+ var currentTimeIndicatorArrow;
+ function startCurrentTimeUpdateInterval() {
+ clearCurrentTimeUpdateInterval();
+
+ //currentTimeUpdateInterval = setInterval(updateCurrentTimeIndicator, 1000);
+ currentTimeUpdateInterval = setInterval(updateCurrentTimeIndicator, 60000);
+ updateCurrentTimeIndicator();
+ }
+
+ function clearCurrentTimeUpdateInterval() {
+ var interval = currentTimeUpdateInterval;
+ if (interval) {
+ clearInterval(interval);
+ }
+ currentTimeUpdateInterval = null;
+ currentTimeIndicatorBar = null;
+ currentTimeIndicatorArrow = null;
+ }
+
+ function updateCurrentTimeIndicator() {
+
+ if (!currentTimeIndicatorBar) {
+ currentTimeIndicatorBar = options.element.querySelector('.currentTimeIndicatorBar');
+ }
+ if (!currentTimeIndicatorArrow) {
+ currentTimeIndicatorArrow = options.element.querySelector('.currentTimeIndicatorArrowContainer');
+ }
+
+ var dateDifference = new Date().getTime() - currentDate.getTime();
+ var pct = dateDifference > 0 ? (dateDifference / totalRendererdMs) : 0;
+ pct = Math.min(pct, 1);
+
+ if (pct <= 0 || pct >= 1) {
+ currentTimeIndicatorBar.classList.add('hide');
+ currentTimeIndicatorArrow.classList.add('hide');
+ } else {
+ currentTimeIndicatorBar.classList.remove('hide');
+ currentTimeIndicatorArrow.classList.remove('hide');
+
+ //pct *= 100;
+ //pct = 100 - pct;
+ //currentTimeIndicatorElement.style.width = (pct * 100) + '%';
+ currentTimeIndicatorBar.style.transform = 'scaleX(' + pct + ')';
+ currentTimeIndicatorArrow.style.transform = 'translateX(' + (pct * 100) + '%)';
+ }
+ }
+
function getChannelLimit(context) {
return registrationServices.validateFeature('livetv').then(function () {
@@ -70,7 +129,7 @@
var limit = 5;
context.querySelector('.guideRequiresUnlock').classList.remove('hide');
- context.querySelector('.unlockText').innerHTML = globalize.translate('LiveTvGuideRequiresUnlock', limit);
+ context.querySelector('.unlockText').innerHTML = globalize.translate('sharedcomponents#LiveTvGuideRequiresUnlock', limit);
return limit;
});
@@ -158,6 +217,11 @@
// Add 30 mins
startDate.setTime(startDate.getTime() + cellDurationMs);
}
+
+ html += '
';
+ html += '
';
+ html += '
';
+ html += 'arrow_drop_down';
html += '
';
return html;
@@ -201,7 +265,7 @@
return curr.ChannelId == channel.Id;
});
- html += '
';
+ html += '
';
for (var i = 0, length = programs.length; i < length; i++) {
@@ -249,7 +313,14 @@
addAccent = false;
}
- html += '
';
if (program.IsHD && options.showHdIcon) {
- html += '
';
+ html += '
hd';
}
if (program.SeriesTimerId) {
- html += '
';
+ html += '
fiber_smart_record';
}
else if (program.TimerId) {
- html += '
';
+ html += '
fiber_manual_record';
}
if (addAccent) {
@@ -299,6 +370,7 @@
// but since mobile browsers are often underpowered,
// it can help performance to get them out of the markup
var showIndicators = window.innerWidth >= 800;
+ showIndicators = false;
var options = {
showHdIcon: showIndicators,
@@ -360,6 +432,19 @@
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 = [];
@@ -400,16 +485,46 @@
// list.push(i);
//});
//channels = list;
+ var activeElement = document.activeElement;
+ var itemId = activeElement && activeElement.getAttribute ? activeElement.getAttribute('data-id') : null;
+ var channelRowId = null;
+
+ if (activeElement) {
+ channelRowId = parentWithClass(activeElement, 'channelPrograms');
+ channelRowId = channelRowId && channelRowId.getAttribute ? channelRowId.getAttribute('data-channelid') : null;
+ }
+
renderChannelHeaders(context, channels, apiClient);
var startDate = date;
var endDate = new Date(startDate.getTime() + msPerDay);
context.querySelector('.timeslotHeaders').innerHTML = getTimeslotHeadersHtml(startDate, endDate);
+ startCurrentTimeUpdateInterval();
items = {};
renderPrograms(context, date, channels, programs);
if (layoutManager.tv) {
- focusManager.autoFocus(context.querySelector('.programGrid'), true);
+
+ var focusElem;
+ if (itemId) {
+ focusElem = context.querySelector('[data-id="' + itemId + '"]')
+ }
+
+ if (focusElem) {
+ focusManager.focus(focusElem);
+ } else {
+
+ var autoFocusParent;
+
+ if (channelRowId) {
+ autoFocusParent = context.querySelector('[data-channelid="' + channelRowId + '"]')
+ }
+
+ if (!autoFocusParent) {
+ autoFocusParent = context.querySelector('.programGrid');
+ }
+ focusManager.autoFocus(autoFocusParent, true);
+ }
}
}
@@ -471,6 +586,8 @@
function changeDate(page, date) {
+ clearCurrentTimeUpdateInterval();
+
var newStartDate = normalizeDateToTimeslot(date);
currentDate = newStartDate;
@@ -626,9 +743,62 @@
target.addEventListener(type, handler, optionsOrCapture);
}
+ function onTimerCreated(e, apiClient, data) {
+
+ var programId = data.ProgramId;
+ // This could be null, not supported by all tv providers
+ var newTimerId = data.Id;
+
+ // find guide cells by program id, ensure timer icon
+ var cells = options.element.querySelectorAll('.programCell[data-id="' + programId + '"]');
+ for (var i = 0, length = cells.length; i < length; i++) {
+ var cell = cells[i];
+
+ var icon = cell.querySelector('.timerIcon');
+ if (!icon) {
+ cell.insertAdjacentHTML('beforeend', '
fiber_manual_record');
+ }
+
+ if (newTimerId) {
+ cell.setAttribute('data-timerid', newTimerId);
+ }
+ }
+ }
+
+ function onSeriesTimerCreated(e, apiClient, data) {
+ }
+
+ function onTimerCancelled(e, apiClient, data) {
+ var id = data.Id;
+ // find guide cells by timer id, remove timer icon
+ var cells = options.element.querySelectorAll('.programCell[data-timerid="' + id + '"]');
+ for (var i = 0, length = cells.length; i < length; i++) {
+ var cells = cells[i];
+ var icon = cell.querySelector('.timerIcon');
+ if (icon) {
+ icon.parentNode.removeChild(icon);
+ }
+ cell.removeAttribute('data-timerid');
+ }
+ }
+
+ function onSeriesTimerCancelled(e, apiClient, data) {
+ var id = data.Id;
+ // find guide cells by timer id, remove timer icon
+ var cells = options.element.querySelectorAll('.programCell[data-seriestimerid="' + id + '"]');
+ for (var i = 0, length = cells.length; i < length; i++) {
+ var cells = cells[i];
+ var icon = cell.querySelector('.seriesTimerIcon');
+ if (icon) {
+ icon.parentNode.removeChild(icon);
+ }
+ cell.removeAttribute('data-seriestimerid');
+ }
+ }
+
require(['text!./tvguide.template.html'], function (template) {
var context = options.element;
- context.innerHTML = globalize.translateDocument(template, 'core');
+ context.innerHTML = globalize.translateDocument(template, 'sharedcomponents');
var programGrid = context.querySelector('.programGrid');
var timeslotHeaders = context.querySelector('.timeslotHeaders');
@@ -662,6 +832,11 @@
events.trigger(self, 'load');
+ events.on(serverNotifications, 'TimerCreated', onTimerCreated);
+ events.on(serverNotifications, 'SeriesTimerCreated', onSeriesTimerCreated);
+ events.on(serverNotifications, 'TimerCancelled', onTimerCancelled);
+ events.on(serverNotifications, 'SeriesTimerCancelled', onSeriesTimerCancelled);
+
self.refresh();
});
};
diff --git a/dashboard-ui/bower_components/emby-webcomponents/guide/tvguide.template.html b/dashboard-ui/bower_components/emby-webcomponents/guide/tvguide.template.html
index 33b8a7406f..e6e31f8703 100644
--- a/dashboard-ui/bower_components/emby-webcomponents/guide/tvguide.template.html
+++ b/dashboard-ui/bower_components/emby-webcomponents/guide/tvguide.template.html
@@ -18,5 +18,8 @@
-
${ButtonUnlockGuide}
+
+ check
+ ${UnlockGuide}
+
\ No newline at end of file
diff --git a/dashboard-ui/bower_components/emby-webcomponents/icons/mediainfo.html b/dashboard-ui/bower_components/emby-webcomponents/icons/mediainfo.html
deleted file mode 100644
index b0805324c8..0000000000
--- a/dashboard-ui/bower_components/emby-webcomponents/icons/mediainfo.html
+++ /dev/null
@@ -1,45 +0,0 @@
-
-
-
-
-
-
diff --git a/dashboard-ui/bower_components/emby-webcomponents/icons/nav.html b/dashboard-ui/bower_components/emby-webcomponents/icons/nav.html
deleted file mode 100644
index 85ea900784..0000000000
--- a/dashboard-ui/bower_components/emby-webcomponents/icons/nav.html
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
-
-
diff --git a/dashboard-ui/bower_components/emby-webcomponents/images/imagehelper.js b/dashboard-ui/bower_components/emby-webcomponents/images/imagehelper.js
index 1fa0235aab..df22363c3e 100644
--- a/dashboard-ui/bower_components/emby-webcomponents/images/imagehelper.js
+++ b/dashboard-ui/bower_components/emby-webcomponents/images/imagehelper.js
@@ -4,6 +4,29 @@ define(['visibleinviewport', 'imageFetcher', 'layoutManager', 'events', 'browser
var thresholdY;
var windowSize;
+ 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;
+ }
+
+ return false;
+ }();
+
+ function resetWindowSize() {
+ windowSize = {
+ innerHeight: window.innerHeight,
+ innerWidth: window.innerWidth
+ };
+ }
+
function resetThresholds() {
var x = screen.availWidth;
@@ -19,33 +42,29 @@ define(['visibleinviewport', 'imageFetcher', 'layoutManager', 'events', 'browser
resetWindowSize();
}
- window.addEventListener("orientationchange", resetThresholds);
- window.addEventListener('resize', resetThresholds);
- events.on(layoutManager, 'modechange', resetThresholds);
-
- var wheelEvent = (document.implementation.hasFeature('Event.wheel', '3.0') ? 'wheel' : 'mousewheel');
-
- function resetWindowSize() {
- windowSize = {
- innerHeight: window.innerHeight,
- innerWidth: window.innerWidth
- };
+ if (!supportsIntersectionObserver) {
+ window.addEventListener("orientationchange", resetThresholds);
+ window.addEventListener('resize', resetThresholds);
+ events.on(layoutManager, 'modechange', resetThresholds);
+ resetThresholds();
}
- resetThresholds();
function isVisible(elem) {
return visibleinviewport(elem, true, thresholdX, thresholdY, windowSize);
}
+ var wheelEvent = (document.implementation.hasFeature('Event.wheel', '3.0') ? 'wheel' : 'mousewheel');
var self = {};
+ var enableFade = browser.animate && !browser.mobile && !browser.operaTv;
+
function fillImage(elem, source, enableEffects) {
if (!source) {
source = elem.getAttribute('data-src');
}
if (source) {
- if (self.enableFade && enableEffects !== false) {
+ if (enableFade && !layoutManager.tv && enableEffects !== false) {
imageFetcher.loadImage(elem, source).then(fadeIn);
} else {
imageFetcher.loadImage(elem, source);
@@ -56,10 +75,12 @@ define(['visibleinviewport', 'imageFetcher', 'layoutManager', 'events', 'browser
function fadeIn(elem) {
+ var duration = layoutManager.tv ? 160 : 300;
+
var keyframes = [
{ opacity: '0', offset: 0 },
{ opacity: '1', offset: 1 }];
- var timing = { duration: 300, iterations: 1 };
+ var timing = { duration: duration, iterations: 1 };
elem.animate(keyframes, timing);
}
@@ -88,30 +109,28 @@ define(['visibleinviewport', 'imageFetcher', 'layoutManager', 'events', 'browser
target.addEventListener(type, handler, optionsOrCapture);
}
- function unveilWithIntersection(images) {
+ function unveilWithIntersection(images, root) {
var filledCount = 0;
+ var options = {};
+
+ //options.rootMargin = "300%";
+
var observer = new IntersectionObserver(function (entries) {
for (var j = 0, length2 = entries.length; j < length2; j++) {
var entry = entries[j];
- var intersectionRatio = entry.intersectionRatio;
- if (intersectionRatio) {
-
- var target = entry.target;
- observer.unobserve(target);
- fillImage(target);
- filledCount++;
- }
+ var target = entry.target;
+ observer.unobserve(target);
+ fillImage(target);
+ filledCount++;
}
if (filledCount >= images.length) {
- //observer.disconnect();
+ observer.disconnect();
}
},
- {
- /* Using default options. Details below */
- }
+ options
);
// Start observing an element
for (var i = 0, length = images.length; i < length; i++) {
@@ -119,30 +138,14 @@ define(['visibleinviewport', 'imageFetcher', 'layoutManager', 'events', 'browser
}
}
- 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;
- }
-
- return false;
- }();
-
- function unveilElements(images) {
+ function unveilElements(images, root) {
if (!images.length) {
return;
}
if (supportsIntersectionObserver) {
- unveilWithIntersection(images);
+ unveilWithIntersection(images, root);
return;
}
@@ -216,7 +219,7 @@ define(['visibleinviewport', 'imageFetcher', 'layoutManager', 'events', 'browser
function lazyChildren(elem) {
- unveilElements(elem.getElementsByClassName('lazy'));
+ unveilElements(elem.getElementsByClassName('lazy'), elem);
}
function getPrimaryImageAspectRatio(items) {
diff --git a/dashboard-ui/bower_components/emby-webcomponents/indicators/indicators.css b/dashboard-ui/bower_components/emby-webcomponents/indicators/indicators.css
new file mode 100644
index 0000000000..0ce002f1a1
--- /dev/null
+++ b/dashboard-ui/bower_components/emby-webcomponents/indicators/indicators.css
@@ -0,0 +1,15 @@
+.itemProgressBar {
+ background: rgba(0,0,0,.5);
+ position: relative;
+}
+
+.itemProgressBarForeground {
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+}
+
+.timerIndicator {
+ color: #CB272A;
+}
\ No newline at end of file
diff --git a/dashboard-ui/bower_components/emby-webcomponents/indicators/indicators.js b/dashboard-ui/bower_components/emby-webcomponents/indicators/indicators.js
new file mode 100644
index 0000000000..0afb8f4ae5
--- /dev/null
+++ b/dashboard-ui/bower_components/emby-webcomponents/indicators/indicators.js
@@ -0,0 +1,111 @@
+define(['css!./indicators.css', 'material-icons'], function () {
+
+ function enableProgressIndicator(item) {
+
+ if (item.MediaType == 'Video') {
+ if (item.Type != 'TvChannel') {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ function getProgressHtml(pct) {
+
+ return '
';
+ }
+
+ function getProgressBarHtml(item) {
+
+ if (enableProgressIndicator(item)) {
+ if (item.Type == "Recording" && item.CompletionPercentage) {
+
+ return getProgressHtml(item.CompletionPercentage);
+ }
+
+ var userData = item.UserData;
+ if (userData) {
+ var pct = userData.PlayedPercentage;
+
+ if (pct && pct < 100) {
+
+ return getProgressHtml(pct);
+ }
+ }
+ }
+
+ return '';
+ }
+
+ 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 != 'TvChannel') {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ function getPlayedIndicator(item) {
+
+ if (enablePlayedIndicator(item)) {
+
+ var userData = item.UserData || {};
+
+ if (userData.UnplayedItemCount) {
+ return '
' + userData.UnplayedItemCount + '
';
+ }
+
+ if (userData.PlayedPercentage && userData.PlayedPercentage >= 100 || (userData.Played)) {
+ return '
check
';
+ }
+ }
+
+ return '';
+ }
+
+ function getCountIndicatorHtml(count) {
+
+ return '
' + count + '
';
+ }
+
+ function getChildCountIndicatorHtml(item, options) {
+
+ var minCount = 0;
+
+ if (options) {
+ minCount = options.minCount || minCount;
+ }
+
+ if (item.ChildCount && item.ChildCount > minCount) {
+ return getCountIndicatorHtml(item.ChildCount);
+ }
+
+ return '';
+ }
+
+ function getTimerIndicator(item) {
+
+ if (item.SeriesTimerId) {
+ return '
fiber_smart_record';
+ }
+ if (item.TimerId) {
+ return '
fiber_manual_record';
+ }
+
+ return '';
+ }
+
+ return {
+ getProgressBarHtml: getProgressBarHtml,
+ getPlayedIndicatorHtml: getPlayedIndicator,
+ getChildCountIndicatorHtml: getChildCountIndicatorHtml,
+ enableProgressIndicator: enableProgressIndicator,
+ getTimerIndicator: getTimerIndicator,
+ enablePlayedIndicator: enablePlayedIndicator
+ };
+});
\ No newline at end of file
diff --git a/dashboard-ui/bower_components/emby-webcomponents/itemcontextmenu.js b/dashboard-ui/bower_components/emby-webcomponents/itemcontextmenu.js
index ead7a4a4ae..67b09637a1 100644
--- a/dashboard-ui/bower_components/emby-webcomponents/itemcontextmenu.js
+++ b/dashboard-ui/bower_components/emby-webcomponents/itemcontextmenu.js
@@ -1,4 +1,4 @@
-define(['apphost', 'globalize', 'connectionManager'], function (appHost, globalize, connectionManager) {
+define(['apphost', 'globalize', 'connectionManager', 'itemHelper'], function (appHost, globalize, connectionManager, itemHelper) {
function getCommands(options) {
@@ -11,6 +11,20 @@ define(['apphost', 'globalize', 'connectionManager'], function (appHost, globali
var commands = [];
+ if (itemHelper.supportsAddingToCollection(item)) {
+ commands.push({
+ name: globalize.translate('sharedcomponents#AddToCollection'),
+ id: 'addtocollection'
+ });
+ }
+
+ if (itemHelper.supportsAddingToPlaylist(item)) {
+ commands.push({
+ name: globalize.translate('sharedcomponents#AddToPlaylist'),
+ id: 'addtoplaylist'
+ });
+ }
+
if (item.CanDelete) {
commands.push({
name: globalize.translate('sharedcomponents#Delete'),
@@ -18,6 +32,15 @@ define(['apphost', 'globalize', 'connectionManager'], function (appHost, globali
});
}
+ if (user.Policy.IsAdministrator) {
+ if (item.MediaType == 'Video' && item.Type != 'TvChannel' && item.Type != 'Program' && item.LocationType != 'Virtual') {
+ commands.push({
+ name: globalize.translate('sharedcomponents#EditSubtitles'),
+ id: 'editsubtitles'
+ });
+ }
+ }
+
if (item.CanDownload && appHost.supports('filedownload')) {
commands.push({
name: globalize.translate('sharedcomponents#Download'),
@@ -54,6 +77,30 @@ define(['apphost', 'globalize', 'connectionManager'], function (appHost, globali
switch (id) {
+ case 'addtocollection':
+ {
+ require(['collectionEditor'], function (collectionEditor) {
+
+ new collectionEditor().show({
+ items: [itemId],
+ serverId: serverId
+
+ }).then(reject, reject);
+ });
+ break;
+ }
+ case 'addtoplaylist':
+ {
+ require(['playlistEditor'], function (playlistEditor) {
+
+ new playlistEditor().show({
+ items: [itemId],
+ serverId: serverId
+
+ }).then(reject, reject);
+ });
+ break;
+ }
case 'download':
{
require(['fileDownloader'], function (fileDownloader) {
@@ -71,6 +118,15 @@ define(['apphost', 'globalize', 'connectionManager'], function (appHost, globali
reject();
});
+ break;
+ }
+ case 'editsubtitles':
+ {
+ require(['subtitleEditor'], function (subtitleEditor) {
+
+ var serverId = apiClient.serverInfo().Id;
+ subtitleEditor.show(itemId, serverId).then(resolve, reject);
+ });
break;
}
case 'refresh':
@@ -127,17 +183,11 @@ define(['apphost', 'globalize', 'connectionManager'], function (appHost, globali
function refresh(apiClient, itemId) {
- apiClient.refreshItem(itemId, {
-
- Recursive: true,
- ImageRefreshMode: 'FullRefresh',
- MetadataRefreshMode: 'FullRefresh',
- ReplaceAllImages: false,
- ReplaceAllMetadata: true
- });
-
- require(['toast'], function (toast) {
- toast(globalize.translate('sharedcomponents#RefreshQueued'));
+ require(['refreshDialog'], function (refreshDialog) {
+ new refreshDialog({
+ itemIds: [itemId],
+ serverId: apiClient.serverInfo().Id
+ }).show();
});
}
diff --git a/dashboard-ui/bower_components/emby-webcomponents/itemhelper.js b/dashboard-ui/bower_components/emby-webcomponents/itemhelper.js
index 6bb706adbd..1056f685f2 100644
--- a/dashboard-ui/bower_components/emby-webcomponents/itemhelper.js
+++ b/dashboard-ui/bower_components/emby-webcomponents/itemhelper.js
@@ -48,7 +48,25 @@ define([], function () {
return name;
}
+ function supportsAddingToCollection(item) {
+ var invalidTypes = ['Person', 'Genre', 'MusicGenre', 'Studio', 'GameGenre', 'BoxSet', 'Playlist', 'UserView', 'CollectionFolder', 'Audio', 'TvChannel', 'Program', 'MusicAlbum', 'Timer'];
+
+ 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";
+ }
+
return {
- getDisplayName: getDisplayName
+ getDisplayName: getDisplayName,
+ supportsAddingToCollection: supportsAddingToCollection,
+ supportsAddingToPlaylist: supportsAddingToPlaylist
};
});
\ No newline at end of file
diff --git a/dashboard-ui/bower_components/emby-webcomponents/listview/listview.css b/dashboard-ui/bower_components/emby-webcomponents/listview/listview.css
new file mode 100644
index 0000000000..05f6974b60
--- /dev/null
+++ b/dashboard-ui/bower_components/emby-webcomponents/listview/listview.css
@@ -0,0 +1,107 @@
+button.listItem {
+ background: transparent;
+ border: 0 !important;
+ cursor: pointer;
+ outline: none !important;
+ color: inherit;
+ width: 100%;
+ vertical-align: middle;
+ font-family: inherit;
+ font-size: inherit;
+}
+
+.listItem {
+ display: flex;
+ align-items: center;
+ text-align: left;
+ padding: .25em 1.25em !important;
+}
+
+ .listItem.largeImage {
+ padding: 1em 0 1em 1em;
+ }
+
+ .listItem > *:not(.listItemBody) {
+ flex-shrink: 0;
+ }
+
+.listItemBody {
+ flex-grow: 1;
+ padding: .85em 1.25em;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+ .listItemBody h3 {
+ margin: 0;
+ font-weight: normal;
+ padding: .25em 0;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+
+.layout-tv .listItemBody h3 {
+ padding: 0;
+}
+
+.listItemBodyText {
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.listItemImage {
+ width: 7.4vh;
+ height: 7.4vh;
+ background-repeat: no-repeat;
+ background-size: contain;
+ flex-shrink: 0;
+}
+
+.listItemIcon {
+ width: 3vh;
+ height: 3vh;
+ font-size: 3vh;
+}
+
+.listItem.largeImage .listItemImage {
+ width: 45vh;
+ height: 30vh;
+ background-position: center center;
+ position: relative;
+ margin-right: 2%;
+ margin-left: 1%;
+}
+
+.listItemImage .itemProgressBar {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+}
+
+.listItem .secondary {
+ color: #737373;
+}
+
+.listItem:focus .secondary {
+ color: inherit !important;
+}
+
+.listItem {
+ transition: transform .2s ease-out;
+}
+
+ .listItem:focus {
+ transform: scale(1.025, 1.025);
+ }
+
+.paperList {
+ padding: .5em 0;
+ margin: 1em auto;
+ 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);
+}
+
+ .paperList.clear {
+ box-shadow: none !important;
+ background-color: transparent !important;
+ }
diff --git a/dashboard-ui/bower_components/emby-webcomponents/listview/listview.js b/dashboard-ui/bower_components/emby-webcomponents/listview/listview.js
new file mode 100644
index 0000000000..f987dc5981
--- /dev/null
+++ b/dashboard-ui/bower_components/emby-webcomponents/listview/listview.js
@@ -0,0 +1,142 @@
+define(['itemHelper', 'mediaInfo', 'indicators', 'css!./listview'], function (itemHelper, mediaInfo, indicators) {
+
+ function getListViewHtml(items, options) {
+
+ var outerHtml = "";
+
+ var index = 0;
+ var groupTitle = '';
+ var action = options.action || 'link';
+
+ var isLargeStyle = options.imageSize == 'large';
+ var enableOverview = options.enableOverview;
+
+ outerHtml += items.map(function (item) {
+
+ var html = '';
+
+ var cssClass = "itemAction listItem";
+
+ var downloadWidth = 80;
+
+ if (isLargeStyle) {
+ cssClass += " largeImage";
+ downloadWidth = 500;
+ }
+
+ html += '
';
+
+ var imgUrl = Emby.Models.imageUrl(item, {
+ width: downloadWidth,
+ type: "Primary"
+ });
+
+ if (!imgUrl) {
+ imgUrl = Emby.Models.thumbImageUrl(item, {
+ width: downloadWidth,
+ type: "Thumb"
+ });
+ }
+
+ if (imgUrl) {
+ html += '';
+ } else {
+ html += '
';
+ }
+
+ var indicatorsHtml = '';
+ indicatorsHtml += indicators.getPlayedIndicatorHtml(item);
+
+ if (indicatorsHtml) {
+ html += '
' + indicatorsHtml + '
';
+ }
+
+ var progressHtml = indicators.getProgressBarHtml(item);
+
+ if (progressHtml) {
+ html += progressHtml;
+ }
+ html += '
';
+
+ var textlines = [];
+
+ if (options.showParentTitle) {
+ if (item.Type == 'Episode') {
+ textlines.push(item.SeriesName || ' ');
+ } else if (item.Type == 'MusicAlbum') {
+ textlines.push(item.AlbumArtist || ' ');
+ }
+ }
+
+ var displayName = itemHelper.getDisplayName(item);
+
+ if (options.showIndexNumber && item.IndexNumber != null) {
+ displayName = item.IndexNumber + ". " + displayName;
+ }
+ textlines.push(displayName);
+
+ if (item.Type == 'Audio') {
+ textlines.push(item.ArtistItems.map(function (a) {
+ return a.Name;
+
+ }).join(', ') || ' ');
+ }
+
+ var lineCount = textlines.length;
+ if (!options.enableSideMediaInfo) {
+ lineCount++;
+ }
+ if (enableOverview && item.Overview) {
+ lineCount++;
+ }
+
+ html += '
';
+
+ for (var i = 0, textLinesLength = textlines.length; i < textLinesLength; i++) {
+
+ if (i == 0 && isLargeStyle) {
+ html += '
';
+ }
+ else if (i == 0) {
+ html += '';
+ } else {
+ html += '
';
+ }
+ html += textlines[i] || ' ';
+ if (i == 0 && isLargeStyle) {
+ html += '';
+ } else {
+ html += '
';
+ }
+ }
+
+ if (!options.enableSideMediaInfo) {
+ html += '
' + mediaInfo.getPrimaryMediaInfoHtml(item) + '
';
+ }
+
+ if (enableOverview && item.Overview) {
+ html += '
';
+ html += item.Overview;
+ html += '
';
+ }
+
+ html += '
';
+
+ if (options.enableSideMediaInfo) {
+ html += '
' + mediaInfo.getPrimaryMediaInfoHtml(item) + '
';
+ }
+
+ html += '';
+
+ index++;
+ return html;
+
+ }).join('');
+
+ return outerHtml;
+ }
+
+ return {
+ getListViewHtml: getListViewHtml
+ };
+});
\ No newline at end of file
diff --git a/dashboard-ui/bower_components/emby-webcomponents/loading/loading-lite.css b/dashboard-ui/bower_components/emby-webcomponents/loading/loading-lite.css
new file mode 100644
index 0000000000..8af19e9048
--- /dev/null
+++ b/dashboard-ui/bower_components/emby-webcomponents/loading/loading-lite.css
@@ -0,0 +1,522 @@
+.mdl-spinner {
+ display: inline-block;
+ position: relative;
+ width: 28px;
+ height: 28px;
+}
+
+ .mdl-spinner.is-active {
+ -webkit-animation: mdl-spinner__container-rotate 1568.23529412ms linear infinite;
+ animation: mdl-spinner__container-rotate 1568.23529412ms linear infinite;
+ }
+
+@-webkit-keyframes mdl-spinner__container-rotate {
+ to {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+
+@keyframes mdl-spinner__container-rotate {
+ to {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+
+.mdl-spinner__layer {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ opacity: 0;
+}
+
+.mdl-spinner__layer-1 {
+ border-color: rgb(66,165,245);
+}
+
+.mdl-spinner--single-color .mdl-spinner__layer-1 {
+ border-color: rgb(63,81,181);
+}
+
+.mdl-spinner.is-active .mdl-spinner__layer-1 {
+ -webkit-animation: mdl-spinner__fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both, mdl-spinner__layer-1-fade-in-out 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
+ animation: mdl-spinner__fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both, mdl-spinner__layer-1-fade-in-out 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
+}
+
+.mdl-spinner__layer-2 {
+ border-color: rgb(244,67,54);
+}
+
+.mdl-spinner--single-color .mdl-spinner__layer-2 {
+ border-color: rgb(63,81,181);
+}
+
+.mdl-spinner.is-active .mdl-spinner__layer-2 {
+ -webkit-animation: mdl-spinner__fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both, mdl-spinner__layer-2-fade-in-out 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
+ animation: mdl-spinner__fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both, mdl-spinner__layer-2-fade-in-out 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
+}
+
+.mdl-spinner__layer-3 {
+ border-color: rgb(253,216,53);
+}
+
+.mdl-spinner--single-color .mdl-spinner__layer-3 {
+ border-color: rgb(63,81,181);
+}
+
+.mdl-spinner.is-active .mdl-spinner__layer-3 {
+ -webkit-animation: mdl-spinner__fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both, mdl-spinner__layer-3-fade-in-out 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
+ animation: mdl-spinner__fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both, mdl-spinner__layer-3-fade-in-out 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
+}
+
+.mdl-spinner__layer-4 {
+ border-color: rgb(76,175,80);
+}
+
+.mdl-spinner--single-color .mdl-spinner__layer-4 {
+ border-color: rgb(63,81,181);
+}
+
+.mdl-spinner.is-active .mdl-spinner__layer-4 {
+ -webkit-animation: mdl-spinner__fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both, mdl-spinner__layer-4-fade-in-out 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
+ animation: mdl-spinner__fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both, mdl-spinner__layer-4-fade-in-out 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
+}
+
+@-webkit-keyframes mdl-spinner__fill-unfill-rotate {
+ 12.5% {
+ -webkit-transform: rotate(135deg);
+ transform: rotate(135deg);
+ }
+
+ 25% {
+ -webkit-transform: rotate(270deg);
+ transform: rotate(270deg);
+ }
+
+ 37.5% {
+ -webkit-transform: rotate(405deg);
+ transform: rotate(405deg);
+ }
+
+ 50% {
+ -webkit-transform: rotate(540deg);
+ transform: rotate(540deg);
+ }
+
+ 62.5% {
+ -webkit-transform: rotate(675deg);
+ transform: rotate(675deg);
+ }
+
+ 75% {
+ -webkit-transform: rotate(810deg);
+ transform: rotate(810deg);
+ }
+
+ 87.5% {
+ -webkit-transform: rotate(945deg);
+ transform: rotate(945deg);
+ }
+
+ to {
+ -webkit-transform: rotate(1080deg);
+ transform: rotate(1080deg);
+ }
+}
+
+@keyframes mdl-spinner__fill-unfill-rotate {
+ 12.5% {
+ -webkit-transform: rotate(135deg);
+ transform: rotate(135deg);
+ }
+
+ 25% {
+ -webkit-transform: rotate(270deg);
+ transform: rotate(270deg);
+ }
+
+ 37.5% {
+ -webkit-transform: rotate(405deg);
+ transform: rotate(405deg);
+ }
+
+ 50% {
+ -webkit-transform: rotate(540deg);
+ transform: rotate(540deg);
+ }
+
+ 62.5% {
+ -webkit-transform: rotate(675deg);
+ transform: rotate(675deg);
+ }
+
+ 75% {
+ -webkit-transform: rotate(810deg);
+ transform: rotate(810deg);
+ }
+
+ 87.5% {
+ -webkit-transform: rotate(945deg);
+ transform: rotate(945deg);
+ }
+
+ to {
+ -webkit-transform: rotate(1080deg);
+ transform: rotate(1080deg);
+ }
+}
+
+/**
+* HACK: Even though the intention is to have the current .mdl-spinner__layer-N
+* at `opacity: 1`, we set it to `opacity: 0.99` instead since this forces Chrome
+* to do proper subpixel rendering for the elements being animated. This is
+* especially visible in Chrome 39 on Ubuntu 14.04. See:
+*
+* - https://github.com/Polymer/paper-spinner/issues/9
+* - https://code.google.com/p/chromium/issues/detail?id=436255
+*/
+@-webkit-keyframes mdl-spinner__layer-1-fade-in-out {
+ from {
+ opacity: 0.99;
+ }
+
+ 25% {
+ opacity: 0.99;
+ }
+
+ 26% {
+ opacity: 0;
+ }
+
+ 89% {
+ opacity: 0;
+ }
+
+ 90% {
+ opacity: 0.99;
+ }
+
+ 100% {
+ opacity: 0.99;
+ }
+}
+
+@keyframes mdl-spinner__layer-1-fade-in-out {
+ from {
+ opacity: 0.99;
+ }
+
+ 25% {
+ opacity: 0.99;
+ }
+
+ 26% {
+ opacity: 0;
+ }
+
+ 89% {
+ opacity: 0;
+ }
+
+ 90% {
+ opacity: 0.99;
+ }
+
+ 100% {
+ opacity: 0.99;
+ }
+}
+
+@-webkit-keyframes mdl-spinner__layer-2-fade-in-out {
+ from {
+ opacity: 0;
+ }
+
+ 15% {
+ opacity: 0;
+ }
+
+ 25% {
+ opacity: 0.99;
+ }
+
+ 50% {
+ opacity: 0.99;
+ }
+
+ 51% {
+ opacity: 0;
+ }
+}
+
+@keyframes mdl-spinner__layer-2-fade-in-out {
+ from {
+ opacity: 0;
+ }
+
+ 15% {
+ opacity: 0;
+ }
+
+ 25% {
+ opacity: 0.99;
+ }
+
+ 50% {
+ opacity: 0.99;
+ }
+
+ 51% {
+ opacity: 0;
+ }
+}
+
+@-webkit-keyframes mdl-spinner__layer-3-fade-in-out {
+ from {
+ opacity: 0;
+ }
+
+ 40% {
+ opacity: 0;
+ }
+
+ 50% {
+ opacity: 0.99;
+ }
+
+ 75% {
+ opacity: 0.99;
+ }
+
+ 76% {
+ opacity: 0;
+ }
+}
+
+@keyframes mdl-spinner__layer-3-fade-in-out {
+ from {
+ opacity: 0;
+ }
+
+ 40% {
+ opacity: 0;
+ }
+
+ 50% {
+ opacity: 0.99;
+ }
+
+ 75% {
+ opacity: 0.99;
+ }
+
+ 76% {
+ opacity: 0;
+ }
+}
+
+@-webkit-keyframes mdl-spinner__layer-4-fade-in-out {
+ from {
+ opacity: 0;
+ }
+
+ 65% {
+ opacity: 0;
+ }
+
+ 75% {
+ opacity: 0.99;
+ }
+
+ 90% {
+ opacity: 0.99;
+ }
+
+ 100% {
+ opacity: 0;
+ }
+}
+
+@keyframes mdl-spinner__layer-4-fade-in-out {
+ from {
+ opacity: 0;
+ }
+
+ 65% {
+ opacity: 0;
+ }
+
+ 75% {
+ opacity: 0.99;
+ }
+
+ 90% {
+ opacity: 0.99;
+ }
+
+ 100% {
+ opacity: 0;
+ }
+}
+
+/**
+* Patch the gap that appear between the two adjacent
+* div.mdl-spinner__circle-clipper while the spinner is rotating
+* (appears on Chrome 38, Safari 7.1, and IE 11).
+*
+* Update: the gap no longer appears on Chrome when .mdl-spinner__layer-N's
+* opacity is 0.99, but still does on Safari and IE.
+*/
+.mdl-spinner__gap-patch {
+ position: absolute;
+ box-sizing: border-box;
+ top: 0;
+ left: 45%;
+ width: 10%;
+ height: 100%;
+ overflow: hidden;
+ border-color: inherit;
+}
+
+ .mdl-spinner__gap-patch .mdl-spinner__circle {
+ width: 1000%;
+ left: -450%;
+ }
+
+.mdl-spinner__circle-clipper {
+ display: inline-block;
+ position: relative;
+ width: 50%;
+ height: 100%;
+ overflow: hidden;
+ border-color: inherit;
+}
+
+ .mdl-spinner__circle-clipper .mdl-spinner__circle {
+ width: 200%;
+ }
+
+.mdl-spinner__circle {
+ box-sizing: border-box;
+ height: 100%;
+ border-width: 3px;
+ border-style: solid;
+ border-color: inherit;
+ border-bottom-color: transparent !important;
+ border-radius: 50%;
+ -webkit-animation: none;
+ animation: none;
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+}
+
+.mdl-spinner__left .mdl-spinner__circle {
+ border-right-color: transparent !important;
+ -webkit-transform: rotate(129deg);
+ transform: rotate(129deg);
+}
+
+.mdl-spinner.is-active .mdl-spinner__left .mdl-spinner__circle {
+ -webkit-animation: mdl-spinner__left-spin 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
+ animation: mdl-spinner__left-spin 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
+}
+
+.mdl-spinner__right .mdl-spinner__circle {
+ left: -100%;
+ border-left-color: transparent !important;
+ -webkit-transform: rotate(-129deg);
+ transform: rotate(-129deg);
+}
+
+.mdl-spinner.is-active .mdl-spinner__right .mdl-spinner__circle {
+ -webkit-animation: mdl-spinner__right-spin 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
+ animation: mdl-spinner__right-spin 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both;
+}
+
+@-webkit-keyframes mdl-spinner__left-spin {
+ from {
+ -webkit-transform: rotate(130deg);
+ transform: rotate(130deg);
+ }
+
+ 50% {
+ -webkit-transform: rotate(-5deg);
+ transform: rotate(-5deg);
+ }
+
+ to {
+ -webkit-transform: rotate(130deg);
+ transform: rotate(130deg);
+ }
+}
+
+@keyframes mdl-spinner__left-spin {
+ from {
+ -webkit-transform: rotate(130deg);
+ transform: rotate(130deg);
+ }
+
+ 50% {
+ -webkit-transform: rotate(-5deg);
+ transform: rotate(-5deg);
+ }
+
+ to {
+ -webkit-transform: rotate(130deg);
+ transform: rotate(130deg);
+ }
+}
+
+@-webkit-keyframes mdl-spinner__right-spin {
+ from {
+ -webkit-transform: rotate(-130deg);
+ transform: rotate(-130deg);
+ }
+
+ 50% {
+ -webkit-transform: rotate(5deg);
+ transform: rotate(5deg);
+ }
+
+ to {
+ -webkit-transform: rotate(-130deg);
+ transform: rotate(-130deg);
+ }
+}
+
+@keyframes mdl-spinner__right-spin {
+ from {
+ -webkit-transform: rotate(-130deg);
+ transform: rotate(-130deg);
+ }
+
+ 50% {
+ -webkit-transform: rotate(5deg);
+ transform: rotate(5deg);
+ }
+
+ to {
+ -webkit-transform: rotate(-130deg);
+ transform: rotate(-130deg);
+ }
+}
+
+.docspinner {
+ margin-top: -5vh;
+ margin-left: -5vh;
+ width: 10vh;
+ height: 10vh;
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ z-index: 9999999;
+ contain: layout style;
+}
+
+.loadingHide {
+ display: none !important;
+}
diff --git a/dashboard-ui/bower_components/emby-webcomponents/loading/loading-lite.js b/dashboard-ui/bower_components/emby-webcomponents/loading/loading-lite.js
index a39bc0fa7e..d167062417 100644
--- a/dashboard-ui/bower_components/emby-webcomponents/loading/loading-lite.js
+++ b/dashboard-ui/bower_components/emby-webcomponents/loading/loading-lite.js
@@ -1,4 +1,4 @@
-define(['MaterialSpinner', 'css!./loading'], function () {
+define(['css!./loading-lite'], function () {
var loadingElem;
@@ -15,8 +15,9 @@ define(['MaterialSpinner', 'css!./loading'], function () {
elem.classList.add('mdl-spinner');
elem.classList.add('mdl-js-spinner');
+ elem.innerHTML = '';
+
document.body.appendChild(elem);
- componentHandler.upgradeElement(elem, 'MaterialSpinner');
}
elem.classList.add('is-active');
diff --git a/dashboard-ui/bower_components/emby-webcomponents/mediainfo/mediainfo.css b/dashboard-ui/bower_components/emby-webcomponents/mediainfo/mediainfo.css
index 0910dab318..759ef7f8a0 100644
--- a/dashboard-ui/bower_components/emby-webcomponents/mediainfo/mediainfo.css
+++ b/dashboard-ui/bower_components/emby-webcomponents/mediainfo/mediainfo.css
@@ -2,9 +2,10 @@
margin: 0 1em 0 0;
}
-iron-icon.mediaInfoItem {
+i.mediaInfoItem {
width: 3vh;
height: 3vh;
+ font-size: 3vh;
margin-right: .6em;
}
@@ -21,10 +22,11 @@ iron-icon.mediaInfoItem {
padding-bottom: 0;
}
- .starRatingContainer iron-icon {
+ .starRatingContainer i {
color: #CB272A;
width: 3vh;
height: 3vh;
+ font-size: 3vh;
}
.mediaInfoItem.criticRating {
@@ -54,12 +56,14 @@ iron-icon.mediaInfoItem {
text-transform: uppercase;
}
-.layout-tv iron-icon.mediaInfoItem {
+.layout-tv i.mediaInfoItem {
width: 4vh;
height: 4vh;
+ font-size: 4vh;
}
-.layout-tv .starRatingContainer iron-icon {
+.layout-tv .starRatingContainer i {
width: 3.4vh;
height: 3.4vh;
+ font-size: 3.4vh;
}
diff --git a/dashboard-ui/bower_components/emby-webcomponents/mediainfo/mediainfo.js b/dashboard-ui/bower_components/emby-webcomponents/mediainfo/mediainfo.js
index 9d3172794f..43c8d7b9f2 100644
--- a/dashboard-ui/bower_components/emby-webcomponents/mediainfo/mediainfo.js
+++ b/dashboard-ui/bower_components/emby-webcomponents/mediainfo/mediainfo.js
@@ -1,4 +1,4 @@
-define(['datetime', 'globalize', 'embyRouter', 'html!./../icons/mediainfo.html', 'css!./mediainfo.css'], function (datetime, globalize, embyRouter) {
+define(['datetime', 'globalize', 'embyRouter', 'material-icons', 'css!./mediainfo.css'], function (datetime, globalize, embyRouter) {
function getProgramInfoHtml(item, options) {
var html = '';
@@ -42,12 +42,12 @@ define(['datetime', 'globalize', 'embyRouter', 'html!./../icons/mediainfo.html',
if (item.SeriesTimerId) {
miscInfo.push({
- html: ''
+ html: 'fiber-smart-record'
});
}
else if (item.TimerId) {
miscInfo.push({
- html: ''
+ html: 'fiber-manual-record'
});
}
@@ -244,7 +244,7 @@ define(['datetime', 'globalize', 'embyRouter', 'html!./../icons/mediainfo.html',
html += getStarIconsHtml(item);
if (item.HasSubtitles && options.subtitles !== false) {
- html += '';
+ html += 'closed_caption';
}
if (item.CriticRating && options.criticRating !== false) {
@@ -321,7 +321,7 @@ define(['datetime', 'globalize', 'embyRouter', 'html!./../icons/mediainfo.html',
if (rating) {
html += '';
- html += '';
+ html += 'star';
html += rating;
html += '
';
}
diff --git a/dashboard-ui/bower_components/emby-webcomponents/playlisteditor/playlisteditor.js b/dashboard-ui/bower_components/emby-webcomponents/playlisteditor/playlisteditor.js
new file mode 100644
index 0000000000..a06c053514
--- /dev/null
+++ b/dashboard-ui/bower_components/emby-webcomponents/playlisteditor/playlisteditor.js
@@ -0,0 +1,259 @@
+define(['shell', 'dialogHelper', 'loading', 'layoutManager', 'connectionManager', 'scrollHelper', 'embyRouter', 'globalize', 'emby-input', 'paper-icon-button-light', 'emby-select', 'material-icons', 'css!./../formdialog', 'emby-button'], function (shell, dialogHelper, loading, layoutManager, connectionManager, scrollHelper, embyRouter, globalize) {
+
+ var lastPlaylistId = '';
+ var currentServerId;
+
+ function parentWithClass(elem, className) {
+
+ while (!elem.classList || !elem.classList.contains(className)) {
+ elem = elem.parentNode;
+
+ if (!elem) {
+ return null;
+ }
+ }
+
+ return elem;
+ }
+
+ function onSubmit(e) {
+
+ loading.show();
+
+ var panel = parentWithClass(this, 'dialog');
+
+ var playlistId = panel.querySelector('#selectPlaylistToAddTo').value;
+ var apiClient = connectionManager.getApiClient(currentServerId);
+
+ if (playlistId) {
+ lastPlaylistId = playlistId;
+ addToPlaylist(apiClient, panel, playlistId);
+ } else {
+ createPlaylist(apiClient, panel);
+ }
+
+ e.preventDefault();
+ return false;
+ }
+
+ function createPlaylist(apiClient, dlg) {
+
+ var url = apiClient.getUrl("Playlists", {
+
+ Name: dlg.querySelector('#txtNewPlaylistName').value,
+ Ids: dlg.querySelector('.fldSelectedItemIds').value || '',
+ userId: apiClient.getCurrentUserId()
+
+ });
+
+ apiClient.ajax({
+ type: "POST",
+ url: url,
+ dataType: "json"
+
+ }).then(function (result) {
+
+ loading.hide();
+
+ var id = result.Id;
+
+ dialogHelper.close(dlg);
+ redirectToPlaylist(apiClient, id);
+ });
+ }
+
+ function redirectToPlaylist(apiClient, id) {
+
+ apiClient.getItem(apiClient.getCurrentUserId(), id).then(function (item) {
+
+ embyRouter.showItem(item);
+ });
+ }
+
+ function addToPlaylist(apiClient, dlg, id) {
+
+ var url = apiClient.getUrl("Playlists/" + id + "/Items", {
+
+ Ids: dlg.querySelector('.fldSelectedItemIds').value || '',
+ userId: apiClient.getCurrentUserId()
+ });
+
+ apiClient.ajax({
+ type: "POST",
+ url: url
+
+ }).then(function () {
+
+ loading.hide();
+
+ dialogHelper.close(dlg);
+
+ require(['toast'], function (toast) {
+ toast(globalize.translate('sharedcomponents#MessageItemsAdded'));
+ });
+ });
+ }
+
+ function triggerChange(select) {
+ select.dispatchEvent(new CustomEvent('change', {}));
+ }
+
+ function populatePlaylists(panel) {
+
+ var select = panel.querySelector('#selectPlaylistToAddTo');
+
+ loading.hide();
+
+ panel.querySelector('.newPlaylistInfo').classList.add('hide');
+
+ var options = {
+
+ Recursive: true,
+ IncludeItemTypes: "Playlist",
+ SortBy: 'SortName'
+ };
+
+ var apiClient = connectionManager.getApiClient(currentServerId);
+ apiClient.getItems(apiClient.getCurrentUserId(), options).then(function (result) {
+
+ var html = '';
+
+ html += '';
+
+ html += result.Items.map(function (i) {
+
+ return '';
+ });
+
+ select.innerHTML = html;
+ select.value = lastPlaylistId || '';
+ triggerChange(select);
+
+ loading.hide();
+ });
+ }
+
+ function getEditorHtml() {
+
+ var html = '';
+
+ html += '';
+ html += '
';
+ html += '
';
+ html += '
';
+ html += '
';
+
+ return html;
+ }
+
+ function initEditor(content, items) {
+
+ content.querySelector('#selectPlaylistToAddTo').addEventListener('change', function () {
+ if (this.value) {
+ content.querySelector('.newPlaylistInfo').classList.add('hide');
+ content.querySelector('#txtNewPlaylistName').removeAttribute('required');
+ } else {
+ content.querySelector('.newPlaylistInfo').classList.remove('hide');
+ content.querySelector('#txtNewPlaylistName').setAttribute('required', 'required');
+ }
+ });
+
+ content.querySelector('form').addEventListener('submit', onSubmit);
+
+ content.querySelector('.fldSelectedItemIds', content).value = items.join(',');
+
+ if (items.length) {
+ content.querySelector('.fldSelectPlaylist').classList.remove('hide');
+ populatePlaylists(content);
+ } else {
+ content.querySelector('.fldSelectPlaylist').classList.add('hide');
+
+ var selectPlaylistToAddTo = content.querySelector('#selectPlaylistToAddTo');
+ selectPlaylistToAddTo.innerHTML = '';
+ selectPlaylistToAddTo.value = '';
+ triggerChange(selectPlaylistToAddTo);
+ }
+ }
+
+ function playlisteditor() {
+
+ var self = this;
+
+ self.show = function (options) {
+
+ var items = options.items || {};
+ currentServerId = options.serverId;
+
+ 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 = '';
+ var title = globalize.translate('sharedcomponents#AddToPlaylist');
+
+ html += '';
+
+ html += getEditorHtml();
+
+ dlg.innerHTML = html;
+ document.body.appendChild(dlg);
+
+ initEditor(dlg, items);
+
+ dlg.querySelector('.btnCancel').addEventListener('click', function () {
+
+ dialogHelper.close(dlg);
+ });
+
+ if (layoutManager.tv) {
+ scrollHelper.centerFocus.on(dlg.querySelector('.dialogContent'), false);
+ }
+
+ return new Promise(function (resolve, reject) {
+
+ dlg.addEventListener('close', resolve);
+ dialogHelper.open(dlg);
+ });
+ };
+ }
+
+ return playlisteditor;
+});
\ No newline at end of file
diff --git a/dashboard-ui/bower_components/emby-webcomponents/prompt/prompt.js b/dashboard-ui/bower_components/emby-webcomponents/prompt/prompt.js
index 2c95a4fcf3..244bed0f49 100644
--- a/dashboard-ui/bower_components/emby-webcomponents/prompt/prompt.js
+++ b/dashboard-ui/bower_components/emby-webcomponents/prompt/prompt.js
@@ -1,10 +1,10 @@
-define(['dialogHelper', 'layoutManager', 'globalize', 'html!./../icons/nav.html', 'css!./style.css', 'paper-button', 'paper-icon-button-light', 'paper-input'], function (dialogHelper, layoutManager, globalize) {
+define(['dialogHelper', 'layoutManager', 'globalize', 'material-icons', 'css!./style.css', 'emby-button', 'paper-icon-button-light', 'emby-input'], function (dialogHelper, layoutManager, globalize) {
function getIcon(icon, cssClass, canFocus, autoFocus) {
var tabIndex = canFocus ? '' : ' tabindex="-1"';
autoFocus = autoFocus ? ' autofocus' : '';
- return '';
+ return '' + icon + '';
}
return function (options) {
@@ -43,7 +43,7 @@ define(['dialogHelper', 'layoutManager', 'globalize', 'html!./../icons/nav.html'
html += '';
if (backButton) {
- html += getIcon('dialog:arrow-back', 'btnPromptExit', false);
+ html += getIcon('arrow_back', 'btnPromptExit', false);
}
if (options.title) {
@@ -54,21 +54,23 @@ define(['dialogHelper', 'layoutManager', 'globalize', 'html!./../icons/nav.html'
html += '
';
@@ -93,18 +95,6 @@ define(['dialogHelper', 'layoutManager', 'globalize', 'html!./../icons/nav.html'
return false;
});
- dlg.querySelector('.btnSubmit').addEventListener('click', function (e) {
-
- // Do a fake form submit this the button isn't a real submit button
- var fakeSubmit = document.createElement('input');
- fakeSubmit.setAttribute('type', 'submit');
- fakeSubmit.style.display = 'none';
- var form = dlg.querySelector('form');
- form.appendChild(fakeSubmit);
- fakeSubmit.click();
- form.removeChild(fakeSubmit);
- });
-
dlg.querySelector('.btnPromptExit').addEventListener('click', function (e) {
dialogHelper.close(dlg);
diff --git a/dashboard-ui/bower_components/emby-webcomponents/prompt/style.css b/dashboard-ui/bower_components/emby-webcomponents/prompt/style.css
index ff22c039ee..106019fb5f 100644
--- a/dashboard-ui/bower_components/emby-webcomponents/prompt/style.css
+++ b/dashboard-ui/bower_components/emby-webcomponents/prompt/style.css
@@ -22,7 +22,10 @@
}
.promptDialog.fullscreen .btnSubmit {
- display: block;
+ display: flex;
+ width: 100%;
+ align-items: center;
+ justify-content: center;
}
.promptDialog.fullscreen .btnPromptExit {
@@ -30,6 +33,10 @@
position: absolute;
top: .5em;
left: .5em;
- width: 5.2vh;
- height: 5.2vh;
}
+
+ .promptDialog.fullscreen .btnPromptExit i {
+ width: 4.4vh;
+ height: 4.4vh;
+ font-size: 4.4vh;
+ }
diff --git a/dashboard-ui/bower_components/emby-webcomponents/recordingcreator/recordingcreator.css b/dashboard-ui/bower_components/emby-webcomponents/recordingcreator/recordingcreator.css
index 4d0f8861e1..986a41151a 100644
--- a/dashboard-ui/bower_components/emby-webcomponents/recordingcreator/recordingcreator.css
+++ b/dashboard-ui/bower_components/emby-webcomponents/recordingcreator/recordingcreator.css
@@ -1,7 +1,14 @@
-.recordingDialog .btnSubmit iron-icon {
+.recordingDialog .btnSubmit .md-icon {
color: #cc3333;
}
.layout-tv .btnHeaderSave {
display: none;
}
+
+@media all and (max-height: 1400px) {
+
+ .layout-tv .recordingDialog .itemOverview {
+ display: none;
+ }
+}
\ No newline at end of file
diff --git a/dashboard-ui/bower_components/emby-webcomponents/recordingcreator/recordingcreator.js b/dashboard-ui/bower_components/emby-webcomponents/recordingcreator/recordingcreator.js
index 782b3fbd8f..1288bf819c 100644
--- a/dashboard-ui/bower_components/emby-webcomponents/recordingcreator/recordingcreator.js
+++ b/dashboard-ui/bower_components/emby-webcomponents/recordingcreator/recordingcreator.js
@@ -1,4 +1,4 @@
-define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'connectionManager', 'require', 'loading', 'scrollHelper', 'scrollStyles', 'paper-checkbox', 'emby-collapsible', 'paper-input', 'paper-icon-button-light', 'css!./../formdialog', 'css!./recordingcreator', 'html!./../icons/mediainfo.html', 'html!./../icons/nav.html'], function (dialogHelper, globalize, layoutManager, mediaInfo, appHost, connectionManager, require, loading, scrollHelper) {
+define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'connectionManager', 'require', 'loading', 'scrollHelper', 'emby-checkbox', 'emby-button', 'emby-collapsible', 'emby-input', 'paper-icon-button-light', 'css!./../formdialog', 'css!./recordingcreator', 'material-icons'], function (dialogHelper, globalize, layoutManager, mediaInfo, appHost, connectionManager, require, loading, scrollHelper) {
var currentProgramId;
var currentServerId;
@@ -38,7 +38,9 @@
}
function hideSeriesRecordingFields(context) {
- slideUpToHide(context.querySelector('#seriesFields'));
+
+ slideUpToHide(context.querySelector('.seriesFields'));
+ slideUpToHide(context.querySelector('.seriesDays'));
context.querySelector('.btnSubmit').classList.remove('hide');
context.querySelector('.supporterContainer').classList.add('hide');
}
@@ -123,8 +125,19 @@
});
}
+ function showSeriesDays(context) {
+
+ if (context.querySelector('#chkAnyTime').checked) {
+ slideUpToHide(context.querySelector('.seriesDays'));
+ } else {
+ slideDownToShow(context.querySelector('.seriesDays'));
+ }
+ }
+
function showSeriesRecordingFields(context, apiClient) {
- slideDownToShow(context.querySelector('#seriesFields'));
+
+ slideDownToShow(context.querySelector('.seriesFields'));
+ showSeriesDays(context);
context.querySelector('.btnSubmit').classList.remove('hide');
getRegistration(currentProgramId, apiClient).then(function (regInfo) {
@@ -195,21 +208,10 @@
});
}
- function onPremiereLinkClicked(e) {
-
- require(['shell'], function (shell) {
- shell.openUrl('https://emby.media/premiere');
- });
- e.preventDefault();
- return false;
- }
-
function init(context) {
var apiClient = connectionManager.getApiClient(currentServerId);
- context.querySelector('.lnkPremiere').addEventListener('click', onPremiereLinkClicked);
-
context.querySelector('#chkRecordSeries').addEventListener('change', function () {
if (this.checked) {
@@ -219,27 +221,16 @@
}
});
- context.querySelector('.btnSubmit').addEventListener('click', function () {
-
- // Do a fake form submit this the button isn't a real submit button
- var fakeSubmit = document.createElement('input');
- fakeSubmit.setAttribute('type', 'submit');
- fakeSubmit.style.display = 'none';
- var form = context.querySelector('form');
- form.appendChild(fakeSubmit);
- fakeSubmit.click();
-
- // Seeing issues in smart tv browsers where the form does not get submitted if the button is removed prior to the submission actually happening
- setTimeout(function () {
- form.removeChild(fakeSubmit);
- }, 500);
- });
-
context.querySelector('.btnCancel').addEventListener('click', function () {
closeDialog(false);
});
+ context.querySelector('#chkAnyTime').addEventListener('change', function () {
+
+ showSeriesDays(context);
+ });
+
context.querySelector('form', context).addEventListener('submit', onSubmit);
var supporterButtons = context.querySelectorAll('.btnSupporter');
@@ -251,12 +242,6 @@
}
}
- if (appHost.supports('externalpremium')) {
- context.querySelector('.btnSupporterForConverting a').href = 'https://emby.media/premiere';
- } else {
- context.querySelector('.btnSupporterForConverting a').href = '#';
- }
-
apiClient.getNamedConfiguration("livetv").then(function (config) {
context.querySelector('#chkConvertRecordings').checked = config.EnableRecordingEncoding;
@@ -330,6 +315,15 @@
});
}
+ function onSupporterButtonClick() {
+ if (appHost.supports('externalpremium')) {
+ require(['shell'], function (shell) {
+ shell.openUrl('https://emby.media/premiere');
+ });
+ } else {
+ }
+ }
+
function reload(context, programId) {
loading.show();
@@ -400,6 +394,8 @@
scrollHelper.centerFocus.on(dlg.querySelector('.dialogContent'), false);
}
+ dlg.querySelector('.btnSupporterForConverting').addEventListener('click', onSupporterButtonClick);
+
hideSeriesRecordingFields(dlg);
init(dlg);
diff --git a/dashboard-ui/bower_components/emby-webcomponents/recordingcreator/recordingcreator.template.html b/dashboard-ui/bower_components/emby-webcomponents/recordingcreator/recordingcreator.template.html
index fdfde02ddf..8f66159a27 100644
--- a/dashboard-ui/bower_components/emby-webcomponents/recordingcreator/recordingcreator.template.html
+++ b/dashboard-ui/bower_components/emby-webcomponents/recordingcreator/recordingcreator.template.html
@@ -1,5 +1,5 @@