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); });