1
0
Fork 0
mirror of https://github.com/jellyfin/jellyfin-web synced 2025-03-30 19:56:21 +00:00

Refactor details page

This commit is contained in:
MrTimscampi 2020-05-10 13:36:26 +02:00
parent a8e45f30ab
commit d57eff1c9b
9 changed files with 128 additions and 107 deletions

View file

@ -577,14 +577,14 @@
padding-left: 32.45vw;
}
.layout-desktop .detailSticky,
.layout-tv .detailSticky {
.layout-desktop .detailRibbon,
.layout-tv .detailRibbon {
margin-top: -7.2em;
height: 7.18em;
}
.layout-desktop .noBackdrop .detailSticky,
.layout-tv .noBackdrop .detailSticky {
.layout-desktop .noBackdrop .detailRibbon,
.layout-tv .noBackdrop .detailRibbon {
margin-top: 0;
}

View file

@ -212,8 +212,15 @@ import 'css!./style';
}
}
export function setLazyImage(element, url) {
element.classList.add('lazy');
element.setAttribute('data-src', url);
lazyImage(element);
}
/* eslint-enable indent */
export default {
serLazyImage: setLazyImage,
fillImages: fillImages,
fillImage: fillImage,
lazyImage: lazyImage,

View file

@ -336,7 +336,14 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
return html = html.join(' / ');
}
function renderName(item, container, isStatic, context) {
/**
* Rneders the item's name block
* @param {Object} item - Item used to render the name.
* @param {HTMLDivElement} container - Container to render the information into.
* @param {Object} context - Application context.
*/
function renderName(item, container, context) {
var parentRoute;
var parentNameHtml = [];
var parentNameLast = false;
@ -364,8 +371,6 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
if (item.SeriesName && 'Season' === item.Type) {
parentRoute = appRouter.getRouteUrl({
Id: item.SeriesId,
Name: item.SeriesName,
Type: 'Series',
IsFolder: true,
ServerId: item.ServerId
@ -501,21 +506,25 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
}
function reloadFromItem(instance, page, params, item, user) {
var context = params.context;
page.querySelector('.detailPagePrimaryContainer').classList.add('detailSticky');
const apiClient = connectionManager.getApiClient(item.ServerId);
renderName(item, page.querySelector('.nameContainer'), false, context);
var apiClient = connectionManager.getApiClient(item.ServerId);
renderSeriesTimerEditor(page, item, apiClient, user);
renderTimerEditor(page, item, apiClient, user);
Emby.Page.setTitle('');
// Start rendering the artwork first
renderImage(page, item, apiClient, user);
renderLogo(page, item, apiClient);
Emby.Page.setTitle('');
setInitialCollapsibleState(page, item, apiClient, context, user);
renderDetails(page, item, apiClient, context);
renderTrackSelections(page, instance, item);
renderBackdrop(item);
renderDetailPageBackdrop(page, item, apiClient);
// Render the main information for the item
page.querySelector('.detailPagePrimaryContainer').classList.add('detailRibbon');
renderName(item, page.querySelector('.nameContainer'), params.context);
renderDetails(page, item, apiClient, params.context);
renderTrackSelections(page, instance, item);
renderSeriesTimerEditor(page, item, apiClient, user);
renderTimerEditor(page, item, apiClient, user);
setInitialCollapsibleState(page, item, apiClient, params.context, user);
var canPlay = reloadPlayButtons(page, item);
if ((item.LocalTrailerCount || item.RemoteTrailers && item.RemoteTrailers.length) && -1 !== playbackManager.getSupportedCommands().indexOf('PlayTrailers')) {
@ -617,18 +626,17 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
}
function renderLogo(page, item, apiClient) {
var url = logoImageUrl(item, apiClient, {
maxWidth: 400
});
var detailLogo = page.querySelector('.detailLogo');
var url = logoImageUrl(item, apiClient, {
maxWidth: detailLogo.clientWidth
});
if (!layoutManager.mobile && !userSettings.enableBackdrops()) {
detailLogo.classList.add('hide');
} else if (url) {
detailLogo.classList.remove('hide');
detailLogo.classList.add('lazy');
detailLogo.setAttribute('data-src', url);
imageLoader.lazyImage(detailLogo);
imageLoader.setLazyImage(detailLogo, url);
} else {
detailLogo.classList.add('hide');
}
@ -654,31 +662,32 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
}
}
function renderLinks(linksElem, item) {
var html = [];
function renderLinks(page, item) {
var externalLinksElem = page.querySelector('.itemExternalLinks');
var links = [];
if (!layoutManager.tv && item.HomePageUrl) {
links.push('<a style="color:inherit;" is="emby-linkbutton" class="button-link" href="' + item.HomePageUrl + '" target="_blank">' + globalize.translate('ButtonWebsite') + '</a>');
links.push(`<a is="emby-linkbutton" class="button-link" href="${item.HomePageUrl}" target="_blank">${globalize.translate('ButtonWebsite')}</a>`);
}
if (item.ExternalUrls) {
for (var i = 0, length = item.ExternalUrls.length; i < length; i++) {
var url = item.ExternalUrls[i];
links.push('<a style="color:inherit;" is="emby-linkbutton" class="button-link" href="' + url.Url + '" target="_blank">' + url.Name + '</a>');
for (let url of item.ExternalUrls) {
links.push(`<a is="emby-linkbutton" class="button-link" href="${url.Url}" target="_blank">${url.Name}</a>`);
}
}
var html = [];
if (links.length) {
html.push(links.join(', '));
}
linksElem.innerHTML = html.join(', ');
externalLinksElem.innerHTML = html.join(', ');
if (html.length) {
linksElem.classList.remove('hide');
externalLinksElem.classList.remove('hide');
} else {
linksElem.classList.add('hide');
externalLinksElem.classList.add('hide');
}
}
@ -828,37 +837,39 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
}
}
function renderOverview(elems, item) {
for (var i = 0, length = elems.length; i < length; i++) {
var elem = elems[i];
function renderOverview(page, item) {
var overviewElemnts = page.querySelectorAll('.overview');
for (let overviewElemnt of overviewElemnts) {
var overview = item.Overview || '';
if (overview) {
elem.innerHTML = overview;
elem.classList.remove('hide');
elem.classList.add('detail-clamp-text');
overviewElemnt.innerHTML = overview;
overviewElemnt.classList.remove('hide');
overviewElemnt.classList.add('detail-clamp-text');
// Grab the sibling element to control the expand state
var expandButton = elem.parentElement.querySelector('.overview-expand');
var expandButton = overviewElemnt.parentElement.querySelector('.overview-expand');
// Detect if we have overflow of text. Based on this StackOverflow answer
// https://stackoverflow.com/a/35157976
if (Math.abs(elem.scrollHeight - elem.offsetHeight) > 2) {
if (Math.abs(overviewElemnt.scrollHeight - overviewElemnt.offsetHeight) > 2) {
expandButton.classList.remove('hide');
} else {
expandButton.classList.add('hide');
}
expandButton.addEventListener('click', toggleLineClamp.bind(null, elem));
expandButton.addEventListener('click', toggleLineClamp.bind(null, overviewElemnt));
var anchors = elem.querySelectorAll('a');
var anchors = overviewElemnt.querySelectorAll('a');
for (var j = 0, length2 = anchors.length; j < length2; j++) {
anchors[j].setAttribute('target', '_blank');
var anchors = overviewElemnt.querySelectorAll('a');
for (let anchor of anchors) {
anchor.setAttribute('target', '_blank');
}
} else {
elem.innerHTML = '';
elem.classList.add('hide');
overviewElemnt.innerHTML = '';
overviewElemnt.classList.add('hide');
}
}
}
@ -902,18 +913,19 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
}
function renderDirector(page, item, context) {
var directors = (item.People || []).filter(function (p) {
return 'Director' === p.Type;
var directors = (item.People || []).filter(function (person) {
return person.Type === 'Director';
});
var html = directors.map(function (p) {
var html = directors.map(function (person) {
return '<a style="color:inherit;" class="button-link" is="emby-linkbutton" href="' + appRouter.getRouteUrl({
Name: p.Name,
Name: person.Name,
Type: 'Person',
ServerId: item.ServerId,
Id: p.Id
Id: person.Id
}, {
context: context
}) + '">' + p.Name + '</a>';
}) + '">' + person.Name + '</a>';
}).join(', ');
var directorsLabel = page.querySelector('.directorsLabel');
@ -929,13 +941,39 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
}
}
function renderDetails(page, item, apiClient, context, isStatic) {
renderSimilarItems(page, item, context);
renderMoreFromSeason(page, item, apiClient);
renderMoreFromArtist(page, item, apiClient);
renderDirector(page, item, context);
renderGenres(page, item, context);
renderChannelGuide(page, apiClient, item);
function renderMiscInfo(page, item) {
const primaryItemMiscInfo = page.querySelectorAll('.itemMiscInfo-primary');
for (let miscInfo of primaryItemMiscInfo) {
mediaInfo.fillPrimaryMediaInfo(miscInfo, item, {
interactive: true,
episodeTitle: false,
subtitles: false
});
if (miscInfo.innerHTML && 'SeriesTimer' !== item.Type) {
miscInfo.classList.remove('hide');
} else {
miscInfo.classList.add('hide');
}
}
const secondaryItemMiscInfo = page.querySelectorAll('.itemMiscInfo-secondary');
for (let miscInfo of secondaryItemMiscInfo) {
mediaInfo.fillSecondaryMediaInfo(miscInfo, item, {
interactive: true
});
if (miscInfo.innerHTML && 'SeriesTimer' !== item.Type) {
miscInfo.classList.remove('hide');
} else {
miscInfo.classList.add('hide');
}
}
}
function renderTagline(page, item) {
var taglineElement = page.querySelector('.tagline');
if (item.Taglines && item.Taglines.length) {
@ -944,45 +982,20 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
} else {
taglineElement.classList.add('hide');
}
var overview = page.querySelector('.overview');
var externalLinksElem = page.querySelector('.itemExternalLinks');
renderOverview([overview], item);
var i;
var itemMiscInfo;
itemMiscInfo = page.querySelectorAll('.itemMiscInfo-primary');
for (i = 0; i < itemMiscInfo.length; i++) {
mediaInfo.fillPrimaryMediaInfo(itemMiscInfo[i], item, {
interactive: true,
episodeTitle: false,
subtitles: false
});
if (itemMiscInfo[i].innerHTML && 'SeriesTimer' !== item.Type) {
itemMiscInfo[i].classList.remove('hide');
} else {
itemMiscInfo[i].classList.add('hide');
}
}
itemMiscInfo = page.querySelectorAll('.itemMiscInfo-secondary');
for (i = 0; i < itemMiscInfo.length; i++) {
mediaInfo.fillSecondaryMediaInfo(itemMiscInfo[i], item, {
interactive: true
});
if (itemMiscInfo[i].innerHTML && 'SeriesTimer' !== item.Type) {
itemMiscInfo[i].classList.remove('hide');
} else {
itemMiscInfo[i].classList.add('hide');
}
}
function renderDetails(page, item, apiClient, context, isStatic) {
renderSimilarItems(page, item, context);
renderMoreFromSeason(page, item, apiClient);
renderMoreFromArtist(page, item, apiClient);
renderDirector(page, item, context);
renderGenres(page, item, context);
renderChannelGuide(page, apiClient, item);
renderTagline(page, item);
renderOverview(page, item);
renderMiscInfo(page, item);
reloadUserDataButtons(page, item);
renderLinks(externalLinksElem, item);
renderLinks(page, item);
renderTags(page, item);
renderSeriesAirTime(page, item, isStatic);
}
@ -1765,17 +1778,18 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
return function (view, params) {
function reload(instance, page, params) {
loading.show();
var apiClient = params.serverId ? connectionManager.getApiClient(params.serverId) : ApiClient;
var promises = [getPromise(apiClient, params), apiClient.getCurrentUser()];
Promise.all(promises).then(function (responses) {
var item = responses[0];
var user = responses[1];
Promise.all([getPromise(apiClient, params), apiClient.getCurrentUser()]).then(([item, user]) => {
currentItem = item;
reloadFromItem(instance, page, params, item, user);
let detailImageContainer = page.querySelector('.detailImageContainer');
const overlayPlayButton = detailImageContainer.querySelector('.cardOverlayFab-primary');
overlayPlayButton.addEventListener('click', onPlayClick);
}).catch((error) => {
console.error('failed to get item or current user: ', error);
});
}

View file

@ -227,7 +227,7 @@ html {
color: #fff !important;
}
.detailSticky {
.detailRibbon {
background: #303030;
background: -webkit-gradient(linear, left top, right top, from(#bcbcbc), color-stop(#a7b4b7), color-stop(#beb5a5), color-stop(#adbec2), to(#b9c7cb));
background: -webkit-linear-gradient(left, #bcbcbc, #a7b4b7, #beb5a5, #adbec2, #b9c7cb);

View file

@ -223,7 +223,7 @@ html {
color: #fff !important;
}
.detailSticky {
.detailRibbon {
background: #303030;
background: -webkit-gradient(linear, left top, right top, from(#291a31), color-stop(#033664), color-stop(#011432), color-stop(#141a3a), to(#291a31));
background: -webkit-linear-gradient(left, #291a31, #033664, #011432, #141a3a, #291a31);

View file

@ -203,11 +203,11 @@ html {
background: rgba(30, 30, 30, 0.9);
}
.detailSticky {
.detailRibbon {
background: rgba(32, 32, 32, 0.8);
}
.noBackdrop .detailSticky {
.noBackdrop .detailRibbon {
background: #202020;
}

View file

@ -221,7 +221,7 @@ html {
color: #fff !important;
}
.detailSticky {
.detailRibbon {
background-color: #303030;
color: #ccc;
color: rgba(255, 255, 255, 0.87);

View file

@ -307,7 +307,7 @@ a[data-role=button] {
color: #f8f8fe !important;
}
.detailSticky {
.detailRibbon {
background: #000420;
background: -moz-linear-gradient(left, #000420 0%, #06256f 18%, #2b052b 38%, #2b052b 68%, #06256f 81%, #000420 100%);
background: -webkit-linear-gradient(left, #000420 0%, #06256f 18%, #2b052b 38%, #2b052b 68%, #06256f 81%, #000420 100%);

View file

@ -209,7 +209,7 @@ html {
color: #fff !important;
}
.detailSticky {
.detailRibbon {
background-color: #081b3b;
}