From de0e45c0c0b0dbe8890537497b0b135aae3279c6 Mon Sep 17 00:00:00 2001 From: MrTimscampi Date: Sat, 9 May 2020 13:49:13 +0200 Subject: [PATCH] Use Card component as poster on details page --- src/assets/css/librarybrowser.css | 6 +- src/components/cardbuilder/cardBuilder.js | 58 +++---- src/controllers/itemDetails.js | 182 +++------------------- 3 files changed, 57 insertions(+), 189 deletions(-) diff --git a/src/assets/css/librarybrowser.css b/src/assets/css/librarybrowser.css index 53018f41d6..9e5c941606 100644 --- a/src/assets/css/librarybrowser.css +++ b/src/assets/css/librarybrowser.css @@ -608,7 +608,7 @@ margin: 1.25em 0; } -.detailImageContainer { +.detailImageContainer .card { position: absolute; top: 50%; float: left; @@ -617,11 +617,11 @@ transform: translateY(-50%); } -.thumbDetailImageContainer { +.detailImageContainer .card.backdropCard { top: 35%; } -.squareDetailImageContainer { +.detailImageContainer .card.squareCard { top: 40%; } diff --git a/src/components/cardbuilder/cardBuilder.js b/src/components/cardbuilder/cardBuilder.js index e540a40211..97a18a713b 100644 --- a/src/components/cardbuilder/cardBuilder.js +++ b/src/components/cardbuilder/cardBuilder.js @@ -1380,7 +1380,6 @@ import 'programStyles'; } if (layoutManager.tv) { - // Don't use the IMG tag with safari because it puts a white border around it cardImageContainerOpen = imgUrl ? ('
') : ('
'); @@ -1398,34 +1397,36 @@ import 'programStyles'; cardBoxClose = '
'; cardScalableClose = '
'; - let indicatorsHtml = ''; + if (!options.disableIndicators || options.disableIndicators === false) { + let indicatorsHtml = ''; - if (options.missingIndicator !== false) { - indicatorsHtml += indicators.getMissingIndicator(item); - } + if (options.missingIndicator !== false) { + indicatorsHtml += indicators.getMissingIndicator(item); + } - indicatorsHtml += indicators.getSyncIndicator(item); - indicatorsHtml += indicators.getTimerIndicator(item); + indicatorsHtml += indicators.getSyncIndicator(item); + indicatorsHtml += indicators.getTimerIndicator(item); - indicatorsHtml += indicators.getTypeIndicator(item); + indicatorsHtml += indicators.getTypeIndicator(item); - if (options.showGroupCount) { + if (options.showGroupCount) { - indicatorsHtml += indicators.getChildCountIndicatorHtml(item, { - minCount: 1 - }); - } else { - indicatorsHtml += indicators.getPlayedIndicatorHtml(item); - } + indicatorsHtml += indicators.getChildCountIndicatorHtml(item, { + minCount: 1 + }); + } else { + indicatorsHtml += indicators.getPlayedIndicatorHtml(item); + } - if (item.Type === 'CollectionFolder' || item.CollectionType) { - const refreshClass = item.RefreshProgress ? '' : ' class="hide"'; - indicatorsHtml += '
'; - requireRefreshIndicator(); - } + if (item.Type === 'CollectionFolder' || item.CollectionType) { + const refreshClass = item.RefreshProgress ? '' : ' class="hide"'; + indicatorsHtml += '
'; + requireRefreshIndicator(); + } - if (indicatorsHtml) { - cardImageContainerOpen += '
' + indicatorsHtml + '
'; + if (indicatorsHtml) { + cardImageContainerOpen += '
' + indicatorsHtml + '
'; + } } if (!imgUrl) { @@ -1474,7 +1475,7 @@ import 'programStyles'; let additionalCardContent = ''; if (layoutManager.desktop) { - additionalCardContent += getHoverMenuHtml(item, action); + additionalCardContent += getHoverMenuHtml(item, action, options); } return '<' + tagName + ' data-index="' + index + '"' + timerAttributes + actionAttribute + ' data-isfolder="' + (item.IsFolder || false) + '" data-serverid="' + (item.ServerId || options.serverId) + '" data-id="' + (item.Id || item.ItemId) + '" data-type="' + item.Type + '"' + mediaTypeData + collectionTypeData + channelIdData + positionTicksData + collectionIdData + playlistIdData + contextData + parentIdData + ' data-prefix="' + prefix + '" class="' + className + '">' + cardImageContainerOpen + innerCardFooter + cardImageContainerClose + overlayButtons + additionalCardContent + cardScalableClose + outerCardFooter + cardBoxClose + ''; @@ -1484,9 +1485,10 @@ import 'programStyles'; * Generates HTML markup for the card overlay. * @param {object} item - Item used to generate the card overlay. * @param {string} action - Action assigned to the overlay. + * @param {Array} options - Card builder options. * @returns {string} HTML markup of the card overlay. */ - function getHoverMenuHtml(item, action) { + function getHoverMenuHtml(item, action, options) { let html = ''; html += '
'; @@ -1501,12 +1503,12 @@ import 'programStyles'; const userData = item.UserData || {}; - if (itemHelper.canMarkPlayed(item)) { + if (itemHelper.canMarkPlayed(item) && !options.disableHoverMenu) { require(['emby-playstatebutton']); html += ''; } - if (itemHelper.canRate(item)) { + if (itemHelper.canRate(item) && !options.disableHoverMenu) { const likes = userData.Likes == null ? '' : userData.Likes; @@ -1514,7 +1516,9 @@ import 'programStyles'; html += ''; } - html += ''; + if (!options.disableHoverMenu) { + html += ''; + } html += '
'; html += ''; diff --git a/src/controllers/itemDetails.js b/src/controllers/itemDetails.js index d5ea90023c..4858e33b7f 100644 --- a/src/controllers/itemDetails.js +++ b/src/controllers/itemDetails.js @@ -470,34 +470,12 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti var imgUrl; var hasbackdrop = false; var itemBackdropElement = page.querySelector('#itemBackdrop'); - var usePrimaryImage = item.MediaType === 'Video' && item.Type !== 'Movie' && item.Type !== 'Trailer' || - item.MediaType && item.MediaType !== 'Video' || - item.Type === 'MusicAlbum' || - item.Type === 'Person'; - if (!layoutManager.mobile && !userSettings.detailsBanner()) { + if (!layoutManager.mobile && !userSettings.enableBackdrops()) { return false; } - if ('Program' === item.Type && item.ImageTags && item.ImageTags.Thumb) { - imgUrl = apiClient.getScaledImageUrl(item.Id, { - type: 'Thumb', - maxWidth: dom.getScreenWidth(), - index: 0, - tag: item.ImageTags.Thumb - }); - imageLoader.lazyImage(itemBackdropElement, imgUrl); - hasbackdrop = true; - } else if (usePrimaryImage && item.ImageTags && item.ImageTags.Primary) { - imgUrl = apiClient.getScaledImageUrl(item.Id, { - type: 'Primary', - maxWidth: dom.getScreenWidth(), - index: 0, - tag: item.ImageTags.Primary - }); - imageLoader.lazyImage(itemBackdropElement, imgUrl); - hasbackdrop = true; - } else if (item.BackdropImageTags && item.BackdropImageTags.length) { + if (item.BackdropImageTags && item.BackdropImageTags.length) { imgUrl = apiClient.getScaledImageUrl(item.Id, { type: 'Backdrop', maxWidth: dom.getScreenWidth(), @@ -515,15 +493,6 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti }); imageLoader.lazyImage(itemBackdropElement, imgUrl); hasbackdrop = true; - } else if (item.ImageTags && item.ImageTags.Thumb) { - imgUrl = apiClient.getScaledImageUrl(item.Id, { - type: 'Thumb', - maxWidth: dom.getScreenWidth(), - index: 0, - tag: item.ImageTags.Thumb - }); - imageLoader.lazyImage(itemBackdropElement, imgUrl); - hasbackdrop = true; } else { itemBackdropElement.style.backgroundImage = ''; } @@ -714,132 +683,25 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function renderDetailImage(page, elem, item, apiClient, editable, imageLoader, indicators) { - if ('SeriesTimer' === item.Type || 'Program' === item.Type) { - editable = false; - } - elem.classList.add('detailimg-hidemobile'); - var imageTags = item.ImageTags || {}; + const itemArray = []; + itemArray.push(item); + const cardHtml = cardBuilder.getCardsHtml(itemArray, { + shape: 'auto', + showTitle: false, + centerText: true, + overlayText: false, + transition: false, + disableIndicators: true, + disableHoverMenu: true, + overlayPlayButton: true, + width: dom.getWindowSize().innerWidth * 0.25 + }); - if (item.PrimaryImageTag) { - imageTags.Primary = item.PrimaryImageTag; - } + elem.innerHTML = cardHtml; - var url; - var html = ''; - var shape = 'portrait'; - var detectRatio = false; - - /* In the following section, getScreenWidth() is multiplied by 0.5 as the posters - are 25vw and we need double the resolution to counter Skia's scaling. */ - // TODO: Find a reliable way to get the poster width - if (imageTags.Primary) { - url = apiClient.getScaledImageUrl(item.Id, { - type: 'Primary', - maxWidth: Math.round(dom.getScreenWidth() * 0.5), - tag: item.ImageTags.Primary - }); - detectRatio = true; - } else if (item.BackdropImageTags && item.BackdropImageTags.length) { - url = apiClient.getScaledImageUrl(item.Id, { - type: 'Backdrop', - maxWidth: Math.round(dom.getScreenWidth() * 0.5), - tag: item.BackdropImageTags[0] - }); - shape = 'thumb'; - } else if (imageTags.Thumb) { - url = apiClient.getScaledImageUrl(item.Id, { - type: 'Thumb', - maxWidth: Math.round(dom.getScreenWidth() * 0.5), - tag: item.ImageTags.Thumb - }); - shape = 'thumb'; - } else if (imageTags.Disc) { - url = apiClient.getScaledImageUrl(item.Id, { - type: 'Disc', - maxWidth: Math.round(dom.getScreenWidth() * 0.5), - tag: item.ImageTags.Disc - }); - shape = 'square'; - } else if (item.AlbumId && item.AlbumPrimaryImageTag) { - url = apiClient.getScaledImageUrl(item.AlbumId, { - type: 'Primary', - maxWidth: Math.round(dom.getScreenWidth() * 0.5), - tag: item.AlbumPrimaryImageTag - }); - shape = 'square'; - } else if (item.SeriesId && item.SeriesPrimaryImageTag) { - url = apiClient.getScaledImageUrl(item.SeriesId, { - type: 'Primary', - maxWidth: Math.round(dom.getScreenWidth() * 0.5), - tag: item.SeriesPrimaryImageTag - }); - } else if (item.ParentPrimaryImageItemId && item.ParentPrimaryImageTag) { - url = apiClient.getScaledImageUrl(item.ParentPrimaryImageItemId, { - type: 'Primary', - maxWidth: Math.round(dom.getScreenWidth() * 0.5), - tag: item.ParentPrimaryImageTag - }); - } - - if (editable && url === undefined) { - html += ""; - } else if (!editable && url === undefined) { - html += "'; - } - - var progressHtml = item.IsFolder || !item.UserData ? '' : indicators.getProgressBarHtml(item); - html += '
'; - - if (progressHtml) { - html += progressHtml; - } - - html += '
'; - elem.innerHTML = html; - - if (detectRatio && item.PrimaryImageAspectRatio) { - if (item.PrimaryImageAspectRatio >= 1.48) { - shape = 'thumb'; - } else if (item.PrimaryImageAspectRatio >= 0.85 && item.PrimaryImageAspectRatio <= 1.34) { - shape = 'square'; - } - } - - if ('thumb' == shape) { - elem.classList.add('thumbDetailImageContainer'); - elem.classList.remove('portraitDetailImageContainer'); - elem.classList.remove('squareDetailImageContainer'); - } else if ('square' == shape) { - elem.classList.remove('thumbDetailImageContainer'); - elem.classList.remove('portraitDetailImageContainer'); - elem.classList.add('squareDetailImageContainer'); - } else { - elem.classList.remove('thumbDetailImageContainer'); - elem.classList.add('portraitDetailImageContainer'); - elem.classList.remove('squareDetailImageContainer'); - } - - if (url) { - imageLoader.lazyImage(elem.querySelector('img'), url); - } + imageLoader.lazyChildren(elem); } function renderImage(page, item, apiClient, user) { @@ -1887,12 +1749,10 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function bindAll(view, selector, eventName, fn) { - var i; - var length; var elems = view.querySelectorAll(selector); - for (i = 0, length = elems.length; i < length; i++) { - elems[i].addEventListener(eventName, fn); + for (let elem of elems) { + elem.addEventListener(eventName, fn); } } @@ -1912,6 +1772,10 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti var user = responses[1]; currentItem = item; reloadFromItem(instance, page, params, item, user); + + let detailImageContainer = page.querySelector('.detailImageContainer'); + const overlayPlayButton = detailImageContainer.querySelector('.cardOverlayFab-primary'); + overlayPlayButton.addEventListener('click', onPlayClick); }); }