diff --git a/dashboard-ui/bower_components/emby-webcomponents/.bower.json b/dashboard-ui/bower_components/emby-webcomponents/.bower.json
index 4f44a24b85..0e9b4ea90e 100644
--- a/dashboard-ui/bower_components/emby-webcomponents/.bower.json
+++ b/dashboard-ui/bower_components/emby-webcomponents/.bower.json
@@ -16,12 +16,12 @@
},
"devDependencies": {},
"ignore": [],
- "version": "1.3.18",
- "_release": "1.3.18",
+ "version": "1.3.21",
+ "_release": "1.3.21",
"_resolution": {
"type": "version",
- "tag": "1.3.18",
- "commit": "127ca5da89083c44351fd0664355f3f521313d5d"
+ "tag": "1.3.21",
+ "commit": "efe918d27e7c9a2c8373494bccf437f5273150c9"
},
"_source": "https://github.com/MediaBrowser/emby-webcomponents.git",
"_target": "^1.2.0",
diff --git a/dashboard-ui/bower_components/emby-webcomponents/browserdeviceprofile.js b/dashboard-ui/bower_components/emby-webcomponents/browserdeviceprofile.js
index 566d19f137..6886f5dd19 100644
--- a/dashboard-ui/bower_components/emby-webcomponents/browserdeviceprofile.js
+++ b/dashboard-ui/bower_components/emby-webcomponents/browserdeviceprofile.js
@@ -329,6 +329,20 @@ define(['browser'], function (browser) {
});
}
+ // Put mp4 ahead of webm
+ if (browser.firefox) {
+ profile.TranscodingProfiles.push({
+ Container: 'mp4',
+ Type: 'Video',
+ AudioCodec: videoAudioCodecs.join(','),
+ VideoCodec: 'h264',
+ Context: 'Streaming',
+ Protocol: 'http',
+ // If audio transcoding is needed, limit to 2 channel
+ MaxAudioChannels: '2'
+ });
+ }
+
if (canPlayWebm) {
profile.TranscodingProfiles.push({
diff --git a/dashboard-ui/bower_components/emby-webcomponents/mediainfo/mediainfo.js b/dashboard-ui/bower_components/emby-webcomponents/mediainfo/mediainfo.js
index 7a8a302653..3cebeefea5 100644
--- a/dashboard-ui/bower_components/emby-webcomponents/mediainfo/mediainfo.js
+++ b/dashboard-ui/bower_components/emby-webcomponents/mediainfo/mediainfo.js
@@ -65,7 +65,9 @@ define(['datetime', 'globalize', 'embyRouter', 'html!./../icons/mediainfo.html',
options = options || {};
var text, date, minutes;
- if (item.Type == "MusicAlbum" || item.MediaType == 'MusicArtist' || item.MediaType == 'Playlist' || item.MediaType == 'MusicGenre') {
+ var showFolderRuntime = item.Type == "MusicAlbum" || item.MediaType == 'MusicArtist' || item.MediaType == 'Playlist' || item.MediaType == 'MusicGenre';
+
+ if (showFolderRuntime) {
var count = item.SongCount || item.ChildCount;
@@ -74,9 +76,8 @@ define(['datetime', 'globalize', 'embyRouter', 'html!./../icons/mediainfo.html',
miscInfo.push(globalize.translate('sharedcomponents#TrackCount', count));
}
- if (item.CumulativeRunTimeTicks) {
-
- miscInfo.push(datetime.getDisplayRunningTime(item.CumulativeRunTimeTicks));
+ if (item.RunTimeTicks) {
+ miscInfo.push(datetime.getDisplayRunningTime(item.RunTimeTicks));
}
}
@@ -206,7 +207,7 @@ define(['datetime', 'globalize', 'embyRouter', 'html!./../icons/mediainfo.html',
}
}
- if (item.RunTimeTicks && item.Type != "Series" && item.Type != 'Program' && options.runtime !== false) {
+ if (item.RunTimeTicks && item.Type != "Series" && item.Type != 'Program' && !showFolderRuntime && options.runtime !== false) {
if (item.Type == "Audio") {
diff --git a/dashboard-ui/bower_components/emby-webcomponents/viewmanager/viewcontainer-lite.js b/dashboard-ui/bower_components/emby-webcomponents/viewmanager/viewcontainer-lite.js
new file mode 100644
index 0000000000..a3d1ffe2d4
--- /dev/null
+++ b/dashboard-ui/bower_components/emby-webcomponents/viewmanager/viewcontainer-lite.js
@@ -0,0 +1,318 @@
+define(['browser'], function (browser) {
+
+ var allPages = document.querySelectorAll('.mainAnimatedPage');
+ var pageContainerCount = allPages.length;
+ var animationDuration = 500;
+ var allowAnimation = true;
+
+ function enableAnimation() {
+
+ if (!allowAnimation) {
+ return false;
+ }
+ if (browser.tv) {
+ return false;
+ }
+
+ return true;
+ }
+
+ function loadView(options) {
+
+ if (options.cancel) {
+ return;
+ }
+
+ cancelActiveAnimations();
+
+ var selected = getSelectedIndex(allPages);
+ var previousAnimatable = selected == -1 ? null : allPages[selected];
+ var pageIndex = selected + 1;
+
+ if (pageIndex >= pageContainerCount) {
+ pageIndex = 0;
+ }
+
+ var html = '
';
+ html += options.view;
+ html += '
';
+
+ var animatable = allPages[pageIndex];
+
+ var currentPage = animatable.querySelector('.page-view');
+
+ if (currentPage) {
+ triggerDestroy(currentPage);
+ }
+
+ animatable.innerHTML = html;
+
+ var view = animatable.querySelector('.page-view');
+
+ if (onBeforeChange) {
+ onBeforeChange(view, false, options);
+ }
+
+ beforeAnimate(allPages, pageIndex, selected);
+
+ // animate here
+ return animate(animatable, previousAnimatable, options.transition, options.isBack).then(function () {
+
+ if (!options.cancel && previousAnimatable) {
+ afterAnimate(allPages, pageIndex);
+ }
+
+ return view;
+ });
+ }
+
+ function beforeAnimate(allPages, newPageIndex, oldPageIndex) {
+ for (var i = 0, length = allPages.length; i < length; i++) {
+ if (newPageIndex == i || oldPageIndex == i) {
+ //allPages[i].classList.remove('hide');
+ } else {
+ allPages[i].classList.add('hide');
+ }
+ }
+ }
+
+ function afterAnimate(allPages, newPageIndex) {
+ for (var i = 0, length = allPages.length; i < length; i++) {
+ if (newPageIndex == i) {
+ //allPages[i].classList.remove('hide');
+ } else {
+ allPages[i].classList.add('hide');
+ }
+ }
+ }
+
+ function animate(newAnimatedPage, oldAnimatedPage, transition, isBack) {
+
+ if (enableAnimation() && newAnimatedPage.animate) {
+ if (transition == 'slide') {
+ return slide(newAnimatedPage, oldAnimatedPage, transition, isBack);
+ } else if (transition == 'fade') {
+ return fade(newAnimatedPage, oldAnimatedPage, transition, isBack);
+ }
+ }
+
+ return nullAnimation(newAnimatedPage, oldAnimatedPage, transition, isBack);
+ }
+
+ function nullAnimation(newAnimatedPage, oldAnimatedPage, transition, isBack) {
+
+ newAnimatedPage.classList.remove('hide');
+ return Promise.resolve();
+ }
+
+ function slide(newAnimatedPage, oldAnimatedPage, transition, isBack) {
+
+ var timings = {
+ duration: 450,
+ iterations: 1,
+ easing: 'ease-out',
+ fill: 'both'
+ }
+
+ var animations = [];
+
+ if (oldAnimatedPage) {
+ var destination = isBack ? '100%' : '-100%';
+
+ animations.push(oldAnimatedPage.animate([
+
+ { transform: 'none', offset: 0 },
+ { transform: 'translateX(' + destination + ')', offset: 1 }
+
+ ], timings));
+ }
+
+ newAnimatedPage.classList.remove('hide');
+
+ var start = isBack ? '-100%' : '100%';
+
+ animations.push(newAnimatedPage.animate([
+
+ { transform: 'translateX(' + start + ')', offset: 0 },
+ { transform: 'none', offset: 1 }
+
+ ], timings));
+
+ currentAnimations = animations;
+
+ return new Promise(function (resolve, reject) {
+ animations[animations.length - 1].onfinish = resolve;
+ });
+ }
+
+ function fade(newAnimatedPage, oldAnimatedPage, transition, isBack) {
+
+ var timings = {
+ duration: animationDuration,
+ iterations: 1,
+ easing: 'ease-out',
+ fill: 'both'
+ }
+
+ var animations = [];
+
+ if (oldAnimatedPage) {
+ animations.push(oldAnimatedPage.animate([
+
+ { opacity: 1, offset: 0 },
+ { opacity: 0, offset: 1 }
+
+ ], timings));
+ }
+
+ newAnimatedPage.classList.remove('hide');
+
+ animations.push(newAnimatedPage.animate([
+
+ { opacity: 0, offset: 0 },
+ { opacity: 1, offset: 1 }
+
+ ], timings));
+
+ currentAnimations = animations;
+
+ return new Promise(function (resolve, reject) {
+ animations[animations.length - 1].onfinish = resolve;
+ });
+ }
+
+ var currentAnimations = [];
+ function cancelActiveAnimations() {
+
+ var animations = currentAnimations;
+ for (var i = 0, length = animations.length; i < length; i++) {
+ cancelAnimation(animations[i]);
+ }
+ }
+
+ function cancelAnimation(animation) {
+
+ try {
+ animation.cancel();
+ } catch (err) {
+ console.log('Error canceling animation: ' + err);
+ }
+ }
+
+ var onBeforeChange;
+ function setOnBeforeChange(fn) {
+ onBeforeChange = fn;
+ }
+
+ function sendResolve(resolve, view) {
+
+ // Don't report completion until the animation has finished, otherwise rendering may not perform well
+ setTimeout(function () {
+
+ resolve(view);
+
+ }, animationDuration);
+ }
+
+ function getSelectedIndex(allPages) {
+ for (var i = 0, length = allPages.length; i < length; i++) {
+ if (!allPages[i].classList.contains('hide')) {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ function tryRestoreView(options) {
+ var url = options.url;
+ var view = document.querySelector(".page-view[data-url='" + url + "']");
+ var page = parentWithClass(view, 'mainAnimatedPage');
+
+ if (view) {
+
+ var index = -1;
+ var pages = document.querySelectorAll('.mainAnimatedPage');
+ for (var i = 0, length = pages.length; i < length; i++) {
+ if (pages[i] == page) {
+ index = i;
+ break;
+ }
+ }
+
+ if (index != -1) {
+
+ if (options.cancel) {
+ return;
+ }
+
+ cancelActiveAnimations();
+
+ var animatable = allPages[index];
+ var selected = getSelectedIndex(allPages);
+ var previousAnimatable = selected == -1 ? null : allPages[selected];
+ var view = animatable.querySelector('.page-view');
+
+ if (onBeforeChange) {
+ onBeforeChange(view, true, options);
+ }
+
+ beforeAnimate(allPages, index, selected);
+
+ return animate(animatable, previousAnimatable, options.transition, options.isBack).then(function () {
+
+ if (!options.cancel && previousAnimatable) {
+ afterAnimate(allPages, index);
+ }
+ return view;
+ });
+ }
+ }
+
+ return Promise.reject();
+ }
+
+ function triggerDestroy(view) {
+ view.dispatchEvent(new CustomEvent("viewdestroy", {}));
+ }
+
+ function reset() {
+
+ var views = document.querySelectorAll(".mainAnimatedPage.hide .page-view");
+
+ for (var i = 0, length = views.length; i < length; i++) {
+
+ var view = views[i];
+ triggerDestroy(view);
+ view.parentNode.removeChild(view);
+ }
+ }
+
+ function parentWithClass(elem, className) {
+
+ while (!elem.classList || !elem.classList.contains(className)) {
+ elem = elem.parentNode;
+
+ if (!elem) {
+ return null;
+ }
+ }
+
+ return elem;
+ }
+
+ function init(isAnimationAllowed) {
+
+ if (allowAnimation && enableAnimation() && !browser.animate) {
+ require(['webAnimations']);
+ }
+ }
+
+ return {
+ loadView: loadView,
+ tryRestoreView: tryRestoreView,
+ reset: reset,
+ setOnBeforeChange: setOnBeforeChange,
+ init: init
+ };
+});
\ No newline at end of file
diff --git a/dashboard-ui/bower_components/emby-webcomponents/viewmanager.js b/dashboard-ui/bower_components/emby-webcomponents/viewmanager/viewmanager.js
similarity index 100%
rename from dashboard-ui/bower_components/emby-webcomponents/viewmanager.js
rename to dashboard-ui/bower_components/emby-webcomponents/viewmanager/viewmanager.js
diff --git a/dashboard-ui/bower_components/polymer/.bower.json b/dashboard-ui/bower_components/polymer/.bower.json
index 3e8a4009a3..bbad7fe7ba 100644
--- a/dashboard-ui/bower_components/polymer/.bower.json
+++ b/dashboard-ui/bower_components/polymer/.bower.json
@@ -34,6 +34,6 @@
"commit": "11c987b2eb3c73b388a79fc8aaea8ca01624f514"
},
"_source": "git://github.com/Polymer/polymer.git",
- "_target": "^1.0.0",
+ "_target": "^1.1.0",
"_originalSource": "Polymer/polymer"
}
\ No newline at end of file
diff --git a/dashboard-ui/components/apphost.js b/dashboard-ui/components/apphost.js
index 062785dab4..0410a4ff24 100644
--- a/dashboard-ui/components/apphost.js
+++ b/dashboard-ui/components/apphost.js
@@ -92,11 +92,10 @@ define(['appStorage', 'browser'], function (appStorage, browser) {
var features = [
'filedownload',
- 'externalpremium'
+ 'externalpremium',
+ 'sharing'
];
- features.push('sharing');
-
return features.indexOf(command.toLowerCase()) != -1;
},
appInfo: function () {
diff --git a/dashboard-ui/scripts/site.js b/dashboard-ui/scripts/site.js
index 57b4ff44e8..fbf90c14f3 100644
--- a/dashboard-ui/scripts/site.js
+++ b/dashboard-ui/scripts/site.js
@@ -1828,12 +1828,13 @@ var AppInfo = {};
define("tvguide", [embyWebComponentsBowerPath + "/guide/guide", 'embyRouter'], returnFirstDependency);
- define("viewManager", [embyWebComponentsBowerPath + "/viewmanager"], function (viewManager) {
+ define("viewManager", [embyWebComponentsBowerPath + "/viewmanager/viewmanager"], function (viewManager) {
viewManager.dispatchPageEvents(true);
return viewManager;
});
- if (Dashboard.isRunningInCordova() && browserInfo.android) {
+ // hack for an android test before browserInfo is loaded
+ if (Dashboard.isRunningInCordova() && window.MainActivity) {
define("shell", ["cordova/android/shell"], returnFirstDependency);
} else {
define("shell", [embyWebComponentsBowerPath + "/shell"], returnFirstDependency);
diff --git a/dashboard-ui/scripts/taskbutton.js b/dashboard-ui/scripts/taskbutton.js
index 2e4311f419..a12abbd186 100644
--- a/dashboard-ui/scripts/taskbutton.js
+++ b/dashboard-ui/scripts/taskbutton.js
@@ -85,7 +85,7 @@
var id = button.getAttribute('data-taskid');
var key = 'scheduledTaskButton' + options.taskKey;
- var expectedValue = new Date().getMonth() + '5';
+ var expectedValue = new Date().getMonth() + '6';
if (appStorage.getItem(key) == expectedValue) {
onScheduledTaskMessageConfirmed(button, id);
@@ -99,7 +99,13 @@
require(['confirm'], function (confirm) {
- confirm(msg, Globalize.translate('HeaderConfirmation')).then(function () {
+ confirm({
+
+ title: Globalize.translate('HeaderConfirmation'),
+ html: msg,
+ text: Globalize.translate('ConfirmMessageScheduledTaskButton') + "\n\n" + Globalize.translate('ButtonScheduledTasks')
+
+ }).then(function () {
appStorage.setItem(key, expectedValue);
onScheduledTaskMessageConfirmed(button, id);
});