diff --git a/dashboard-ui/bower_components/emby-webcomponents/.bower.json b/dashboard-ui/bower_components/emby-webcomponents/.bower.json index 55c82eb283..486302a5e6 100644 --- a/dashboard-ui/bower_components/emby-webcomponents/.bower.json +++ b/dashboard-ui/bower_components/emby-webcomponents/.bower.json @@ -15,12 +15,12 @@ }, "devDependencies": {}, "ignore": [], - "version": "1.4.27", - "_release": "1.4.27", + "version": "1.4.29", + "_release": "1.4.29", "_resolution": { "type": "version", - "tag": "1.4.27", - "commit": "f0b0925d56c650501ba6c92a9413b55201f6b129" + "tag": "1.4.29", + "commit": "7292111f0088d466ef25b0d3a99d17b6e07ff0d0" }, "_source": "https://github.com/MediaBrowser/emby-webcomponents.git", "_target": "^1.2.0", diff --git a/dashboard-ui/bower_components/emby-webcomponents/backdrop/backdrop.js b/dashboard-ui/bower_components/emby-webcomponents/backdrop/backdrop.js index dcc48b8eb3..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; @@ -107,8 +110,6 @@ var elem = getBackdropContainer(); elem.innerHTML = ''; - getSkinContainer().removeAttribute('data-backdroptype'); - if (clearAll) { hasExternalBackdrop = false; } @@ -170,64 +171,146 @@ currentLoadingBackdrop = instance; } - function setBackdrops(items, type) { + 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: Math.min(screen.availWidth || window.innerWidth, 1920) - }); - - setBackdrop(imgUrl, type); - }); + startRotation(images, imageSetId); } else { clearBackdrop(); } } - function setBackdrop(url, type) { + 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) { - setBackdropImage(url); + clearRotation(); - if (type) { - getSkinContainer().setAttribute('data-backdroptype', type); - } else { - getSkinContainer().removeAttribute('data-backdroptype'); - } + setBackdropImage(url); } else { clearBackdrop(); 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 index 941e9c2e0b..18d616bb74 100644 --- a/dashboard-ui/bower_components/emby-webcomponents/emby-button/emby-button.css +++ b/dashboard-ui/bower_components/emby-webcomponents/emby-button/emby-button.css @@ -99,6 +99,8 @@ user-select: none; cursor: pointer; z-index: 0; + min-width: 40px; + min-height: 40px; width: 40px; height: 40px; padding: 8px; @@ -113,39 +115,45 @@ font-weight: 500; text-transform: uppercase; border-radius: 50%; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } - [is=paper-icon-button-light] iron-icon { - width: 100%; - height: 100%; - /* Make sure its on top of the ripple */ - position: relative; - z-index: 1; - } +.layout-tv [is=paper-icon-button-light] { + width: 4vh; + height: 4vh; +} - [is=paper-icon-button-light] img { - width: 100%; - height: 100%; - /* Make sure its on top of the ripple */ - position: relative; - z-index: 1; - } +[is=paper-icon-button-light] iron-icon { + width: 100%; + height: 100%; + /* Make sure its on top of the ripple */ + position: relative; + z-index: 1; +} - [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] img { + width: 100%; + height: 100%; + /* Make sure its on top of the ripple */ + position: relative; + z-index: 1; +} - [is=paper-icon-button-light]:focus:after { - opacity: .3; - } +[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; diff --git a/dashboard-ui/bower_components/emby-webcomponents/guide/guide.css b/dashboard-ui/bower_components/emby-webcomponents/guide/guide.css index c665943f12..3d1f8a3551 100644 --- a/dashboard-ui/bower_components/emby-webcomponents/guide/guide.css +++ b/dashboard-ui/bower_components/emby-webcomponents/guide/guide.css @@ -4,6 +4,25 @@ align-items: initial; } + .tvguide ::-webkit-scrollbar { + width: 10px; + height: 10px; + } + + .tvguide ::-webkit-scrollbar-button:start:decrement, + .tvguide ::-webkit-scrollbar-button:end:increment { + display: none; + } + + .tvguide ::-webkit-scrollbar-track-piece { + background-color: #3b3b3b; + } + + .tvguide ::-webkit-scrollbar-thumb:vertical, .tvguide ::-webkit-scrollbar-thumb:horizontal { + -webkit-border-radius: 2px; + background: #888 no-repeat center; + } + .tvGuideHeader { white-space: nowrap; width: 100%; @@ -105,6 +124,44 @@ position: relative; } +.timeslotHeadersInner { + position: relative; +} + +.currentTimeIndicator { + position: absolute; + bottom: .05em; + left: 0; + width: 100%; + height: 2px; + display: flex; + align-items: flex-end; + transition: all 500ms ease-out; +} + +.layout-tv .currentTimeIndicator { + /* Need to account for the scrollbar not being there */ + margin-left: 4px; +} + +.currentTimeIndicatorBar { + background-color: #52B54B; + height: 2px; + flex-grow: 1; + width: 100%; + margin-left: .65vh; +} + +.currentTimeIndicator iron-icon { + width: 4vh; + height: 4vh; + color: #52B54B; + flex-shrink: 0; + position: relative; + margin-left: -2vh; + top: 1.45vh; +} + .channelPrograms, .timeslotHeadersInner { width: 1800vw; } diff --git a/dashboard-ui/bower_components/emby-webcomponents/guide/guide.js b/dashboard-ui/bower_components/emby-webcomponents/guide/guide.js index 6aba1a7df7..a6e4ed8736 100644 --- a/dashboard-ui/bower_components/emby-webcomponents/guide/guide.js +++ b/dashboard-ui/bower_components/emby-webcomponents/guide/guide.js @@ -11,6 +11,7 @@ }; self.destroy = function () { + clearCurrentTimeUpdateInterval(); itemShortcuts.off(options.element); items = {}; }; @@ -21,6 +22,7 @@ var cellCurationMinutes = 30; var cellDurationMs = cellCurationMinutes * 60 * 1000; var msPerDay = 86400000; + var totalRendererdMs = msPerDay; var currentDate; @@ -56,6 +58,46 @@ loading.hide(); } + var currentTimeUpdateInterval; + var currentTimeIndicatorElement; + function startCurrentTimeUpdateInterval() { + clearCurrentTimeUpdateInterval(); + + //currentTimeUpdateInterval = setInterval(updateCurrentTimeIndicator, 1000); + currentTimeUpdateInterval = setInterval(updateCurrentTimeIndicator, 60000); + updateCurrentTimeIndicator(); + } + + function clearCurrentTimeUpdateInterval() { + var interval = currentTimeUpdateInterval; + if (interval) { + clearInterval(interval); + } + currentTimeUpdateInterval = null; + currentTimeIndicatorElement = null; + } + + function updateCurrentTimeIndicator() { + + if (!currentTimeIndicatorElement) { + currentTimeIndicatorElement = options.element.querySelector('.currentTimeIndicator'); + } + + var dateDifference = new Date().getTime() - currentDate.getTime(); + var pct = dateDifference > 0 ? (dateDifference / totalRendererdMs) : 0; + pct = Math.min(pct, 1); + + if (pct <= 0 || pct >= 1) { + currentTimeIndicatorElement.classList.add('hide'); + } else { + currentTimeIndicatorElement.classList.remove('hide'); + + //pct *= 100; + //pct = 100 - pct; + currentTimeIndicatorElement.style.width = (pct * 100) + '%'; + } + } + function getChannelLimit(context) { return registrationServices.validateFeature('livetv').then(function () { @@ -159,6 +201,13 @@ // Add 30 mins startDate.setTime(startDate.getTime() + cellDurationMs); } + + html += '
'; + html += '
'; + html += '
'; + html += ''; + html += '
'; + html += ''; return html; @@ -436,6 +485,7 @@ var startDate = date; var endDate = new Date(startDate.getTime() + msPerDay); context.querySelector('.timeslotHeaders').innerHTML = getTimeslotHeadersHtml(startDate, endDate); + startCurrentTimeUpdateInterval(); items = {}; renderPrograms(context, date, channels, programs); @@ -522,6 +572,8 @@ function changeDate(page, date) { + clearCurrentTimeUpdateInterval(); + var newStartDate = normalizeDateToTimeslot(date); currentDate = newStartDate; diff --git a/dashboard-ui/bower_components/emby-webcomponents/icons/nav.html b/dashboard-ui/bower_components/emby-webcomponents/icons/nav.html index 2c69896cce..39c6ced14e 100644 --- a/dashboard-ui/bower_components/emby-webcomponents/icons/nav.html +++ b/dashboard-ui/bower_components/emby-webcomponents/icons/nav.html @@ -35,6 +35,7 @@ See [iron-iconset](#iron-iconset) and [iron-iconset-svg](#iron-iconset-svg) for + diff --git a/dashboard-ui/bower_components/iron-resizable-behavior/.bower.json b/dashboard-ui/bower_components/iron-resizable-behavior/.bower.json index cca11d8994..2e765b9324 100644 --- a/dashboard-ui/bower_components/iron-resizable-behavior/.bower.json +++ b/dashboard-ui/bower_components/iron-resizable-behavior/.bower.json @@ -28,14 +28,14 @@ "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" }, "ignore": [], - "homepage": "https://github.com/polymerelements/iron-resizable-behavior", + "homepage": "https://github.com/PolymerElements/iron-resizable-behavior", "_release": "1.0.3", "_resolution": { "type": "version", "tag": "v1.0.3", "commit": "dda1df6aaf452aedf3e52ff0cf69e72439452216" }, - "_source": "git://github.com/polymerelements/iron-resizable-behavior.git", + "_source": "git://github.com/PolymerElements/iron-resizable-behavior.git", "_target": "^1.0.0", - "_originalSource": "polymerelements/iron-resizable-behavior" + "_originalSource": "PolymerElements/iron-resizable-behavior" } \ No newline at end of file diff --git a/dashboard-ui/bower_components/polymer/.bower.json b/dashboard-ui/bower_components/polymer/.bower.json index 680bb70d57..e3120e6882 100644 --- a/dashboard-ui/bower_components/polymer/.bower.json +++ b/dashboard-ui/bower_components/polymer/.bower.json @@ -39,6 +39,6 @@ "commit": "ce5b9fb2d8aa03c698410e2e55cffcfa0b788a3a" }, "_source": "git://github.com/Polymer/polymer.git", - "_target": "^1.2.0", + "_target": "^1.1.0", "_originalSource": "Polymer/polymer" } \ No newline at end of file diff --git a/dashboard-ui/components/tvproviders/xmltv.template.html b/dashboard-ui/components/tvproviders/xmltv.template.html index 6faef9d4e3..455c2c016d 100644 --- a/dashboard-ui/components/tvproviders/xmltv.template.html +++ b/dashboard-ui/components/tvproviders/xmltv.template.html @@ -5,7 +5,7 @@
- +
diff --git a/dashboard-ui/css/librarybrowser.css b/dashboard-ui/css/librarybrowser.css index f749347235..8ac7f660d3 100644 --- a/dashboard-ui/css/librarybrowser.css +++ b/dashboard-ui/css/librarybrowser.css @@ -460,7 +460,7 @@ span.itemCommunityRating:not(:empty) + .userDataIcons { @media all and (max-width: 600px) { .detailFloatingButton { - right: 15px; + right: 15px!important; } } diff --git a/dashboard-ui/scripts/librarylist.js b/dashboard-ui/scripts/librarylist.js index dd75a36af8..a357890966 100644 --- a/dashboard-ui/scripts/librarylist.js +++ b/dashboard-ui/scripts/librarylist.js @@ -1270,6 +1270,7 @@ callback: function (id) { var items = selectedItems.slice(0); + var serverId = ApiClient.serverInfo().Id; switch (id) { @@ -1277,7 +1278,8 @@ require(['collectionEditor'], function (collectionEditor) { new collectionEditor().show({ - items: items + items: items, + serverId: serverId }); }); hideSelections(); diff --git a/dashboard-ui/scripts/site.js b/dashboard-ui/scripts/site.js index 643757361f..22f5f4a841 100644 --- a/dashboard-ui/scripts/site.js +++ b/dashboard-ui/scripts/site.js @@ -1241,7 +1241,7 @@ var Dashboard = { if (enableVlcVideo) { profile.DirectPlayProfiles.push({ - Container: "m4v,3gp,ts,mpegts,mov,xvid,vob,mkv,wmv,asf,ogm,ogv,m2v,avi,mpg,mpeg,mp4,webm", + Container: "m4v,3gp,ts,mpegts,mov,xvid,vob,mkv,wmv,asf,ogm,ogv,m2v,avi,mpg,mpeg,mp4,webm,wtv", Type: 'Video', AudioCodec: 'aac,aac_latm,mp2,mp3,ac3,wma,dca,pcm,PCM_S16LE,PCM_S24LE,opus,flac' }); @@ -2011,6 +2011,15 @@ var AppInfo = {}; }; }); + // mock this for now. not used in this app + define("playbackManager", [], function () { + return { + isPlayingVideo: function () { + return false; + } + }; + }); + // mock this for now. not used in this app define("skinManager", [], function () {