Merge pull request #1206 from MrTimscampi/details-redux

Fix some issues with details page and small redesign
This commit is contained in:
dkanada 2020-06-28 18:10:07 +09:00 committed by GitHub
commit 178d698feb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 494 additions and 543 deletions

View File

@ -24,10 +24,6 @@
padding-top: 7em !important; padding-top: 7em !important;
} }
.layout-mobile .libraryPage {
padding-top: 4em !important;
}
.itemDetailPage { .itemDetailPage {
padding-top: 0 !important; padding-top: 0 !important;
} }
@ -164,6 +160,7 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
contain: layout style paint; contain: layout style paint;
transition: background ease-in-out 0.5s;
} }
.hiddenViewMenuBar .skinHeader { .hiddenViewMenuBar .skinHeader {
@ -438,12 +435,14 @@
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: center; background-position: center;
background-attachment: fixed; background-attachment: fixed;
height: 50vh; height: 40vh;
position: relative; position: relative;
animation: backdrop-fadein 800ms ease-in normal both;
} }
.layout-mobile .itemBackdrop { .layout-mobile .itemBackdrop {
background-attachment: scroll; background-attachment: scroll;
height: 26.5vh;
} }
.layout-desktop .itemBackdrop::after, .layout-desktop .itemBackdrop::after,
@ -463,10 +462,20 @@
.detailPageContent { .detailPageContent {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
padding-left: 2%; padding-left: 32.45vw;
padding-right: 2%; padding-right: 2%;
} }
.layout-mobile .detailPageContent {
padding-left: 5%;
padding-right: 5%;
}
.layout-desktop .detailPageContent .emby-scroller,
.layout-tv .detailPageContent .emby-scroller {
margin-left: 0;
}
.layout-desktop .noBackdrop .detailPageContent, .layout-desktop .noBackdrop .detailPageContent,
.layout-tv .noBackdrop .detailPageContent { .layout-tv .noBackdrop .detailPageContent {
margin-top: 2.5em; margin-top: 2.5em;
@ -477,6 +486,10 @@
margin-top: 0; margin-top: 0;
} }
.detailSectionContent a {
color: inherit;
}
.personBackdrop { .personBackdrop {
background-size: contain; background-size: contain;
} }
@ -495,7 +508,23 @@
.parentName { .parentName {
display: block; display: block;
margin-bottom: 0.5em; margin: 0 0 0;
}
.layout-mobile .parentName {
margin: 0.6em 0 0;
}
.musicParentName {
margin: 0.15em 0 0.2em;
}
.layout-mobile .musicParentName {
margin: -0.25em 0 0.25em;
}
.layout-mobile .itemExternalLinks {
display: none;
} }
.mainDetailButtons { .mainDetailButtons {
@ -503,8 +532,6 @@
-webkit-box-align: center; -webkit-box-align: center;
-webkit-align-items: center; -webkit-align-items: center;
align-items: center; align-items: center;
-webkit-flex-wrap: wrap;
flex-wrap: wrap;
margin: 1em 0; margin: 1em 0;
} }
@ -520,6 +547,35 @@
font-weight: 600; font-weight: 600;
} }
.itemName.originalTitle {
margin: 0.2em 0 0.2em;
}
.itemName.parentNameLast {
margin: 0 0 0;
}
.layout-mobile .itemName.parentNameLast {
margin: 0.4em 0 0.4em;
}
.layout-mobile h1.itemName,
.layout-mobile h1.parentName {
font-size: 1.6em;
}
.itemName.parentNameLast.withOriginalTitle {
margin: 0 0 0;
}
.layout-mobile .itemName.parentNameLast.withOriginalTitle {
margin: 0.6em 0 0;
}
.layout-mobile .itemName.originalTitle {
margin: 0.5em 0 0.5em;
}
.nameContainer { .nameContainer {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -546,6 +602,19 @@
text-align: center; text-align: center;
} }
.layout-mobile .mainDetailButtons {
margin-top: 1em;
margin-bottom: 0.5em;
}
.subtitle {
margin: 0.15em 0 0.2em;
}
.layout-mobile .subtitle {
margin: 0.2em 0 0.2em;
}
.detailPagePrimaryContainer { .detailPagePrimaryContainer {
display: flex; display: flex;
align-items: center; align-items: center;
@ -556,7 +625,7 @@
.layout-mobile .detailPagePrimaryContainer { .layout-mobile .detailPagePrimaryContainer {
display: block; display: block;
position: relative; position: relative;
top: 0; padding: 0.5em 3.3% 0.5em;
} }
.layout-tv #itemDetailPage:not(.noBackdrop) .detailPagePrimaryContainer, .layout-tv #itemDetailPage:not(.noBackdrop) .detailPagePrimaryContainer,
@ -566,13 +635,14 @@
padding-left: 32.45vw; padding-left: 32.45vw;
} }
.layout-desktop .detailSticky, .layout-desktop .detailRibbon,
.layout-tv .detailSticky { .layout-tv .detailRibbon {
margin-top: -7.2em; margin-top: -7.2em;
height: 7.18em;
} }
.layout-desktop .noBackdrop .detailSticky, .layout-desktop .noBackdrop .detailRibbon,
.layout-tv .noBackdrop .detailSticky { .layout-tv .noBackdrop .detailRibbon {
margin-top: 0; margin-top: 0;
} }
@ -584,6 +654,9 @@
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
text-align: left; text-align: left;
min-width: 0;
max-width: 100%;
overflow: hidden;
} }
.layout-mobile .infoText { .layout-mobile .infoText {
@ -594,13 +667,29 @@
margin: 1.25em 0; margin: 1.25em 0;
} }
.detailImageContainer { .layout-mobile .detailPageSecondaryContainer {
position: relative; margin: 1em 0;
margin-top: -25vh; }
margin-bottom: 10vh;
.layout-mobile .detailImageContainer {
display: none;
}
.detailImageContainer .card {
position: absolute;
top: 50%;
float: left; float: left;
width: 25vw; width: 25vw;
z-index: 3; z-index: 3;
transform: translateY(-50%);
}
.detailImageContainer .card.backdropCard {
top: 35%;
}
.detailImageContainer .card.squareCard {
top: 40%;
} }
.layout-desktop .noBackdrop .detailImageContainer, .layout-desktop .noBackdrop .detailImageContainer,
@ -613,11 +702,11 @@
} }
.detailLogo { .detailLogo {
width: 30vw; width: 25vw;
height: 25vh; height: 16vh;
position: absolute; position: absolute;
top: 10vh; top: 10vh;
right: 20vw; right: 25vw;
background-size: contain; background-size: contain;
} }
@ -657,14 +746,19 @@ div.itemDetailGalleryLink.defaultCardBackground {
position: relative; position: relative;
} }
.layout-desktop .detailPageWrapperContainer, .layout-desktop .itemBackdrop,
.layout-tv .detailPageWrapperContainer { .layout-tv .itemBackdrop {
margin-top: 7.2em; height: 40vh;
} }
.layout-tv #itemDetailPage:not(.noBackdrop) .detailPagePrimaryContainer, .layout-desktop .detailPageWrapperContainer,
.layout-desktop #itemDetailPage:not(.noBackdrop) .detailPagePrimaryContainer { .layout-tv .detailPageWrapperContainer {
padding-left: 3.3%; margin-top: 0.1em;
}
.layout-desktop .detailImageContainer .card,
.layout-tv .detailImageContainer .card {
top: 10%;
} }
.btnPlaySimple { .btnPlaySimple {
@ -680,12 +774,12 @@ div.itemDetailGalleryLink.defaultCardBackground {
.emby-button.detailFloatingButton { .emby-button.detailFloatingButton {
position: absolute; position: absolute;
background-color: rgba(0, 0, 0, 0.5) !important; background-color: rgba(0, 0, 0, 0.5);
z-index: 1; z-index: 3;
top: 50%; top: 100%;
left: 50%; left: 90%;
margin: -2.2em 0 0 -2.2em; margin: -2.2em 0 0 -2.2em;
padding: 0.4em !important; padding: 0.4em;
color: rgba(255, 255, 255, 0.76); color: rgba(255, 255, 255, 0.76);
} }
@ -695,16 +789,12 @@ div.itemDetailGalleryLink.defaultCardBackground {
@media all and (max-width: 62.5em) { @media all and (max-width: 62.5em) {
.parentName { .parentName {
margin-bottom: 1em; margin-bottom: 0;
} }
.itemDetailPage { .itemDetailPage {
padding-top: 0 !important; padding-top: 0 !important;
} }
.detailimg-hidemobile {
display: none;
}
} }
@media all and (min-width: 31.25em) { @media all and (min-width: 31.25em) {
@ -868,6 +958,10 @@ div.itemDetailGalleryLink.defaultCardBackground {
} }
} }
.detailVerticalSection .emby-scrollbuttons {
padding-top: 0.4em;
}
.layout-tv .detailVerticalSection { .layout-tv .detailVerticalSection {
margin-bottom: 3.4em !important; margin-bottom: 3.4em !important;
} }
@ -956,6 +1050,10 @@ div.itemDetailGalleryLink.defaultCardBackground {
margin-bottom: 2.7em; margin-bottom: 2.7em;
} }
.layout-mobile .verticalSection-extrabottompadding {
margin-bottom: 1em;
}
.sectionTitleButton, .sectionTitleButton,
.sectionTitleIconButton { .sectionTitleIconButton {
margin-right: 0 !important; margin-right: 0 !important;
@ -981,7 +1079,13 @@ div.itemDetailGalleryLink.defaultCardBackground {
div:not(.sectionTitleContainer-cards) > .sectionTitle-cards { div:not(.sectionTitleContainer-cards) > .sectionTitle-cards {
margin: 0; margin: 0;
padding-top: 1.25em; padding-top: 0.5em;
padding-bottom: 0.2em;
}
.layout-mobile :not(.sectionTitleContainer-cards) > .sectionTitle-cards {
margin: 0;
padding-top: 0.5em;
} }
.sectionTitleButton { .sectionTitleButton {
@ -1134,6 +1238,12 @@ div:not(.sectionTitleContainer-cards) > .sectionTitle-cards {
.trackSelections .selectContainer .selectLabel { .trackSelections .selectContainer .selectLabel {
margin: 0 0.2em 0 0; margin: 0 0.2em 0 0;
line-height: 1.75;
}
.layout-mobile .detailsGroupItem .label,
.layout-mobile .trackSelections .selectContainer .selectLabel {
flex-basis: 4.5em;
} }
.trackSelections .selectContainer .detailTrackSelect { .trackSelections .selectContainer .detailTrackSelect {

View File

@ -16,7 +16,7 @@ function getOffsets(elems) {
return results; return results;
} }
for (let elem of elems) { for (const elem of elems) {
let box = elem.getBoundingClientRect(); let box = elem.getBoundingClientRect();
results.push({ results.push({
@ -135,7 +135,7 @@ export function show(options) {
let renderIcon = false; let renderIcon = false;
let icons = []; let icons = [];
let itemIcon; let itemIcon;
for (let item of options.items) { for (const item of options.items) {
itemIcon = item.icon || (item.selected ? 'check' : null); itemIcon = item.icon || (item.selected ? 'check' : null);

View File

@ -1310,7 +1310,7 @@ import 'programStyles';
} }
const mediaSourceCount = item.MediaSourceCount || 1; const mediaSourceCount = item.MediaSourceCount || 1;
if (mediaSourceCount > 1) { if (mediaSourceCount > 1 && options.disableIndicators !== true) {
innerCardFooter += '<div class="mediaSourceIndicator">' + mediaSourceCount + '</div>'; innerCardFooter += '<div class="mediaSourceIndicator">' + mediaSourceCount + '</div>';
} }
@ -1391,34 +1391,36 @@ import 'programStyles';
cardBoxClose = '</div>'; cardBoxClose = '</div>';
cardScalableClose = '</div>'; cardScalableClose = '</div>';
let indicatorsHtml = ''; if (options.disableIndicators !== true) {
let indicatorsHtml = '';
if (options.missingIndicator !== false) { if (options.missingIndicator !== false) {
indicatorsHtml += indicators.getMissingIndicator(item); indicatorsHtml += indicators.getMissingIndicator(item);
} }
indicatorsHtml += indicators.getSyncIndicator(item); indicatorsHtml += indicators.getSyncIndicator(item);
indicatorsHtml += indicators.getTimerIndicator(item); indicatorsHtml += indicators.getTimerIndicator(item);
indicatorsHtml += indicators.getTypeIndicator(item); indicatorsHtml += indicators.getTypeIndicator(item);
if (options.showGroupCount) { if (options.showGroupCount) {
indicatorsHtml += indicators.getChildCountIndicatorHtml(item, { indicatorsHtml += indicators.getChildCountIndicatorHtml(item, {
minCount: 1 minCount: 1
}); });
} else { } else {
indicatorsHtml += indicators.getPlayedIndicatorHtml(item); indicatorsHtml += indicators.getPlayedIndicatorHtml(item);
} }
if (item.Type === 'CollectionFolder' || item.CollectionType) { if (item.Type === 'CollectionFolder' || item.CollectionType) {
const refreshClass = item.RefreshProgress ? '' : ' class="hide"'; const refreshClass = item.RefreshProgress ? '' : ' class="hide"';
indicatorsHtml += '<div is="emby-itemrefreshindicator"' + refreshClass + ' data-progress="' + (item.RefreshProgress || 0) + '" data-status="' + item.RefreshStatus + '"></div>'; indicatorsHtml += '<div is="emby-itemrefreshindicator"' + refreshClass + ' data-progress="' + (item.RefreshProgress || 0) + '" data-status="' + item.RefreshStatus + '"></div>';
requireRefreshIndicator(); requireRefreshIndicator();
} }
if (indicatorsHtml) { if (indicatorsHtml) {
cardImageContainerOpen += '<div class="cardIndicators">' + indicatorsHtml + '</div>'; cardImageContainerOpen += '<div class="cardIndicators">' + indicatorsHtml + '</div>';
}
} }
if (!imgUrl) { if (!imgUrl) {
@ -1467,7 +1469,7 @@ import 'programStyles';
let additionalCardContent = ''; let additionalCardContent = '';
if (layoutManager.desktop) { 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 + '</' + tagName + '>'; 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 + '</' + tagName + '>';
@ -1477,9 +1479,10 @@ import 'programStyles';
* Generates HTML markup for the card overlay. * Generates HTML markup for the card overlay.
* @param {object} item - Item used to generate the card overlay. * @param {object} item - Item used to generate the card overlay.
* @param {string} action - Action assigned to the overlay. * @param {string} action - Action assigned to the overlay.
* @param {Array} options - Card builder options.
* @returns {string} HTML markup of the card overlay. * @returns {string} HTML markup of the card overlay.
*/ */
function getHoverMenuHtml(item, action) { function getHoverMenuHtml(item, action, options) {
let html = ''; let html = '';
html += '<div class="cardOverlayContainer itemAction" data-action="' + action + '">'; html += '<div class="cardOverlayContainer itemAction" data-action="' + action + '">';
@ -1494,12 +1497,12 @@ import 'programStyles';
const userData = item.UserData || {}; const userData = item.UserData || {};
if (itemHelper.canMarkPlayed(item)) { if (itemHelper.canMarkPlayed(item) && !options.disableHoverMenu) {
require(['emby-playstatebutton']); require(['emby-playstatebutton']);
html += '<button is="emby-playstatebutton" type="button" data-action="none" class="' + btnCssClass + '" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-itemtype="' + item.Type + '" data-played="' + (userData.Played) + '"><span class="material-icons cardOverlayButtonIcon cardOverlayButtonIcon-hover check"></span></button>'; html += '<button is="emby-playstatebutton" type="button" data-action="none" class="' + btnCssClass + '" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-itemtype="' + item.Type + '" data-played="' + (userData.Played) + '"><span class="material-icons cardOverlayButtonIcon cardOverlayButtonIcon-hover check"></span></button>';
} }
if (itemHelper.canRate(item)) { if (itemHelper.canRate(item) && !options.disableHoverMenu) {
const likes = userData.Likes == null ? '' : userData.Likes; const likes = userData.Likes == null ? '' : userData.Likes;
@ -1507,7 +1510,9 @@ import 'programStyles';
html += '<button is="emby-ratingbutton" type="button" data-action="none" class="' + btnCssClass + '" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-itemtype="' + item.Type + '" data-likes="' + likes + '" data-isfavorite="' + (userData.IsFavorite) + '"><span class="material-icons cardOverlayButtonIcon cardOverlayButtonIcon-hover favorite"></span></button>'; html += '<button is="emby-ratingbutton" type="button" data-action="none" class="' + btnCssClass + '" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-itemtype="' + item.Type + '" data-likes="' + likes + '" data-isfavorite="' + (userData.IsFavorite) + '"><span class="material-icons cardOverlayButtonIcon cardOverlayButtonIcon-hover favorite"></span></button>';
} }
html += '<button is="paper-icon-button-light" class="' + btnCssClass + '" data-action="menu"><span class="material-icons cardOverlayButtonIcon cardOverlayButtonIcon-hover more_vert"></span></button>'; if (!options.disableHoverMenu) {
html += '<button is="paper-icon-button-light" class="' + btnCssClass + '" data-action="menu"><span class="material-icons cardOverlayButtonIcon cardOverlayButtonIcon-hover more_vert"></span></button>';
}
html += '</div>'; html += '</div>';
html += '</div>'; html += '</div>';

View File

@ -22,7 +22,7 @@ define(['dom', 'appRouter', 'connectionManager'], function (dom, appRouter, conn
return void appRouter.showItem(items[0]); return void appRouter.showItem(items[0]);
} }
var url = 'itemdetails.html?id=' + itemId + '&serverId=' + serverId; var url = 'details?id=' + itemId + '&serverId=' + serverId;
Dashboard.navigate(url); Dashboard.navigate(url);
}); });
e.stopPropagation(); e.stopPropagation();

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 */ /* eslint-enable indent */
export default { export default {
serLazyImage: setLazyImage,
fillImages: fillImages, fillImages: fillImages,
fillImage: fillImage, fillImage: fillImage,
lazyImage: lazyImage, lazyImage: lazyImage,

View File

@ -1,14 +1,12 @@
define(['apphost', 'globalize'], function (appHost, globalize) { define(['apphost', 'globalize'], function (appHost, globalize) {
'use strict'; 'use strict';
function getDisplayName(item, options) { function getDisplayName(item, options = {}) {
if (!item) { if (!item) {
throw new Error('null item passed into getDisplayName'); throw new Error('null item passed into getDisplayName');
} }
options = options || {};
if (item.Type === 'Timer') { if (item.Type === 'Timer') {
item = item.ProgramInfo || item; item = item.ProgramInfo || item;
} }

View File

@ -125,10 +125,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
var largeTitleTagName = layoutManager.tv ? 'h2' : 'div'; var largeTitleTagName = layoutManager.tv ? 'h2' : 'div';
for (var i = 0, length = textlines.length; i < length; i++) { for (const [i, text] of textlines.entries()) {
var text = textlines[i];
if (!text) { if (!text) {
continue; continue;
} }
@ -434,8 +431,6 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
html += '<div class="' + cssClass + '">'; html += '<div class="' + cssClass + '">';
const moreIcon = 'more_vert';
html += getTextLinesHtml(textlines, isLargeStyle); html += getTextLinesHtml(textlines, isLargeStyle);
if (options.mediaInfo !== false) { if (options.mediaInfo !== false) {
@ -486,10 +481,6 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
html += '<button is="paper-icon-button-light" class="listItemButton itemAction" data-action="addtoplaylist"><span class="material-icons playlist_add"></span></button>'; html += '<button is="paper-icon-button-light" class="listItemButton itemAction" data-action="addtoplaylist"><span class="material-icons playlist_add"></span></button>';
} }
if (options.moreButton !== false) {
html += '<button is="paper-icon-button-light" class="listItemButton itemAction" data-action="menu"><span class="material-icons ' + moreIcon + '"></span></button>';
}
if (options.infoButton) { if (options.infoButton) {
html += '<button is="paper-icon-button-light" class="listItemButton itemAction" data-action="link"><span class="material-icons info_outline"></span></button>'; html += '<button is="paper-icon-button-light" class="listItemButton itemAction" data-action="link"><span class="material-icons info_outline"></span></button>';
} }
@ -503,14 +494,18 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
var userData = item.UserData || {}; var userData = item.UserData || {};
var likes = userData.Likes == null ? '' : userData.Likes; var likes = userData.Likes == null ? '' : userData.Likes;
if (itemHelper.canMarkPlayed(item)) { if (itemHelper.canMarkPlayed(item) && options.enablePlayedButton !== false) {
html += '<button is="emby-playstatebutton" type="button" class="listItemButton paper-icon-button-light" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-itemtype="' + item.Type + '" data-played="' + (userData.Played) + '"><span class="material-icons check"></span></button>'; html += '<button is="emby-playstatebutton" type="button" class="listItemButton paper-icon-button-light" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-itemtype="' + item.Type + '" data-played="' + (userData.Played) + '"><span class="material-icons check"></span></button>';
} }
if (itemHelper.canRate(item)) { if (itemHelper.canRate(item) && options.enableRatingButton !== false) {
html += '<button is="emby-ratingbutton" type="button" class="listItemButton paper-icon-button-light" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-itemtype="' + item.Type + '" data-likes="' + likes + '" data-isfavorite="' + (userData.IsFavorite) + '"><span class="material-icons favorite"></span></button>'; html += '<button is="emby-ratingbutton" type="button" class="listItemButton paper-icon-button-light" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-itemtype="' + item.Type + '" data-likes="' + likes + '" data-isfavorite="' + (userData.IsFavorite) + '"><span class="material-icons favorite"></span></button>';
} }
} }
if (options.moreButton !== false) {
html += '<button is="paper-icon-button-light" class="listItemButton itemAction" data-action="menu"><span class="material-icons more_vert"></span></button>';
}
} }
html += '</div>'; html += '</div>';

View File

@ -41,6 +41,8 @@
width: auto !important; width: auto !important;
height: auto !important; height: auto !important;
font-size: 1.4em; font-size: 1.4em;
margin-right: 0.125em;
color: #f2b01e;
} }
.mediaInfoCriticRating { .mediaInfoCriticRating {

View File

@ -122,10 +122,10 @@ define(['browser', 'datetime', 'backdrop', 'libraryBrowser', 'listView', 'imageL
var artistName; var artistName;
if (item.ArtistItems != null) { if (item.ArtistItems != null) {
artistName = item.ArtistItems[0].Name; artistName = item.ArtistItems[0].Name;
context.querySelector('.nowPlayingAlbum').innerHTML = '<a class="button-link emby-button" is="emby-linkbutton" href="itemdetails.html?id=' + item.AlbumId + `&amp;serverId=${nowPlayingServerId}">${albumName}</a>`; context.querySelector('.nowPlayingAlbum').innerHTML = '<a class="button-link emby-button" is="emby-linkbutton" href="details?id=' + item.AlbumId + `&amp;serverId=${nowPlayingServerId}">${albumName}</a>`;
context.querySelector('.nowPlayingArtist').innerHTML = '<a class="button-link emby-button" is="emby-linkbutton" href="itemdetails.html?id=' + item.ArtistItems[0].Id + `&amp;serverId=${nowPlayingServerId}">${artistName}</a>`; context.querySelector('.nowPlayingArtist').innerHTML = '<a class="button-link emby-button" is="emby-linkbutton" href="details?id=' + item.ArtistItems[0].Id + `&amp;serverId=${nowPlayingServerId}">${artistName}</a>`;
context.querySelector('.contextMenuAlbum').innerHTML = '<a class="button-link emby-button" is="emby-linkbutton" href="itemdetails.html?id=' + item.AlbumId + `&amp;serverId=${nowPlayingServerId}"><span class="actionsheetMenuItemIcon listItemIcon listItemIcon-transparent material-icons album"></span> ` + globalize.translate('ViewAlbum') + '</a>'; context.querySelector('.contextMenuAlbum').innerHTML = '<a class="button-link emby-button" is="emby-linkbutton" href="details?id=' + item.AlbumId + `&amp;serverId=${nowPlayingServerId}"><span class="actionsheetMenuItemIcon listItemIcon listItemIcon-transparent material-icons album"></span> ` + globalize.translate('ViewAlbum') + '</a>';
context.querySelector('.contextMenuArtist').innerHTML = '<a class="button-link emby-button" is="emby-linkbutton" href="itemdetails.html?id=' + item.ArtistItems[0].Id + `&amp;serverId=${nowPlayingServerId}"><span class="actionsheetMenuItemIcon listItemIcon listItemIcon-transparent material-icons person"></span> ` + globalize.translate('ViewArtist') + '</a>'; context.querySelector('.contextMenuArtist').innerHTML = '<a class="button-link emby-button" is="emby-linkbutton" href="details?id=' + item.ArtistItems[0].Id + `&amp;serverId=${nowPlayingServerId}"><span class="actionsheetMenuItemIcon listItemIcon listItemIcon-transparent material-icons person"></span> ` + globalize.translate('ViewArtist') + '</a>';
} else { } else {
artistName = item.Artists; artistName = item.Artists;
context.querySelector('.nowPlayingAlbum').innerHTML = albumName; context.querySelector('.nowPlayingAlbum').innerHTML = albumName;
@ -136,12 +136,12 @@ define(['browser', 'datetime', 'backdrop', 'libraryBrowser', 'listView', 'imageL
} else if (item.Type == 'Episode') { } else if (item.Type == 'Episode') {
if (item.SeasonName != null) { if (item.SeasonName != null) {
var seasonName = item.SeasonName; var seasonName = item.SeasonName;
context.querySelector('.nowPlayingSeason').innerHTML = '<a class="button-link emby-button" is="emby-linkbutton" href="itemdetails.html?id=' + item.SeasonId + `&amp;serverId=${nowPlayingServerId}">${seasonName}</a>`; context.querySelector('.nowPlayingSeason').innerHTML = '<a class="button-link emby-button" is="emby-linkbutton" href="details?id=' + item.SeasonId + `&amp;serverId=${nowPlayingServerId}">${seasonName}</a>`;
} }
if (item.SeriesName != null) { if (item.SeriesName != null) {
var seriesName = item.SeriesName; var seriesName = item.SeriesName;
if (item.SeriesId != null) { if (item.SeriesId != null) {
context.querySelector('.nowPlayingSerie').innerHTML = '<a class="button-link emby-button" is="emby-linkbutton" href="itemdetails.html?id=' + item.SeriesId + `&amp;serverId=${nowPlayingServerId}">${seriesName}</a>`; context.querySelector('.nowPlayingSerie').innerHTML = '<a class="button-link emby-button" is="emby-linkbutton" href="details?id=' + item.SeriesId + `&amp;serverId=${nowPlayingServerId}">${seriesName}</a>`;
} else { } else {
context.querySelector('.nowPlayingSerie').innerHTML = seriesName; context.querySelector('.nowPlayingSerie').innerHTML = seriesName;
} }

View File

@ -1,8 +1,5 @@
<div id="itemDetailPage" data-role="page" class="page libraryPage itemDetailPage noSecondaryNavPage selfBackdropPage noBackdrop" data-backbutton="true"> <div id="itemDetailPage" data-role="page" class="page libraryPage itemDetailPage noSecondaryNavPage selfBackdropPage" data-backbutton="true">
<div id="itemBackdrop" class="itemBackdrop"> <div id="itemBackdrop" class="itemBackdrop">
<button is="emby-button" type="button" class="btnPlay detailFloatingButton hide fab autoSize" title="${ButtonPlay}" data-mode="resume">
<span class="material-icons play_arrow"></span>
</button>
</div> </div>
<div class="detailLogo"></div> <div class="detailLogo"></div>
@ -15,94 +12,75 @@
</div> </div>
<div class="mainDetailButtons"> <div class="mainDetailButtons">
<button is="emby-button" type="button" class="button-flat btnResume hide detailButton detailButtonHideonMobile" data-mode="resume"> <button is="emby-button" type="button" class="button-flat btnResume hide detailButton" title="${ButtonResume}" data-mode="resume">
<div class="detailButton-content"> <div class="detailButton-content">
<span class="material-icons detailButton-icon play_arrow"></span> <span class="material-icons detailButton-icon play_arrow"></span>
<div class="detailButton-text">${ButtonResume}</div>
</div> </div>
</button> </button>
<button is="emby-button" type="button" class="button-flat btnPlay hide detailButton detailButtonHideonMobile" data-mode="play"> <button is="emby-button" type="button" class="button-flat btnPlay hide detailButton" title="${ButtonPlay}" data-mode="play">
<div class="detailButton-content"> <div class="detailButton-content">
<span class="material-icons detailButton-icon play_arrow"></span> <span class="material-icons detailButton-icon play_arrow"></span>
<div class="detailButton-text">${ButtonPlay}</div>
</div> </div>
</button> </button>
<button is="emby-button" type="button" class="button-flat btnDownload hide detailButton"> <button is="emby-button" type="button" class="button-flat btnDownload hide detailButton" title="${ButtonDownload}">
<div class="detailButton-content"> <div class="detailButton-content">
<span class="material-icons detailButton-icon get_app"></span> <span class="material-icons detailButton-icon get_app"></span>
<div class="detailButton-text">${ButtonDownload}</div>
</div> </div>
</button> </button>
<button is="emby-button" type="button" class="button-flat btnPlayTrailer hide detailButton"> <button is="emby-button" type="button" class="button-flat btnPlayTrailer hide detailButton" title="${ButtonTrailer}">
<div class="detailButton-content"> <div class="detailButton-content">
<span class="material-icons detailButton-icon theaters"></span> <span class="material-icons detailButton-icon theaters"></span>
<div class="detailButton-text">${ButtonTrailer}</div>
</div> </div>
</button> </button>
<button is="emby-button" type="button" class="button-flat btnInstantMix hide detailButton"> <button is="emby-button" type="button" class="button-flat btnInstantMix hide detailButton" title="${HeaderInstantMix}">
<div class="detailButton-content"> <div class="detailButton-content">
<span class="material-icons detailButton-icon explore"></span> <span class="material-icons detailButton-icon explore"></span>
<div class="detailButton-text">${HeaderInstantMix}</div>
</div> </div>
</button> </button>
<button is="emby-button" type="button" class="button-flat btnShuffle hide detailButton"> <button is="emby-button" type="button" class="button-flat btnShuffle hide detailButton" title="${ButtonShuffle}">
<div class="detailButton-content"> <div class="detailButton-content">
<span class="material-icons detailButton-icon shuffle"></span> <span class="material-icons detailButton-icon shuffle"></span>
<div class="detailButton-text">${ButtonShuffle}</div>
</div> </div>
</button> </button>
<button is="emby-button" type="button" class="button-flat btnCancelSeriesTimer hide detailButton"> <button is="emby-button" type="button" class="button-flat btnCancelSeriesTimer hide detailButton" title="${CancelSeries}">
<div class="detailButton-content"> <div class="detailButton-content">
<span class="material-icons detailButton-icon delete"></span> <span class="material-icons detailButton-icon delete"></span>
<div class="detailButton-text">${CancelSeries}</div>
</div> </div>
</button> </button>
<button is="emby-button" type="button" class="button-flat btnCancelTimer hide detailButton"> <button is="emby-button" type="button" class="button-flat btnCancelTimer hide detailButton" title="${StopRecording}">
<div class="detailButton-content"> <div class="detailButton-content">
<span class="material-icons detailButton-icon stop"></span> <span class="material-icons detailButton-icon stop"></span>
<div class="detailButton-text">${StopRecording}</div>
</div> </div>
</button> </button>
<button is="emby-button" type="button" class="button-flat btnDeleteItem hide detailButton"> <button is="emby-playstatebutton" type="button" class="button-flat btnPlaystate hide detailButton" title="">
<div class="detailButton-content">
<span class="material-icons detailButton-icon delete"></span>
<div class="detailButton-text">${Delete}</div>
</div>
</button>
<button is="emby-playstatebutton" type="button" class="button-flat btnPlaystate hide detailButton">
<div class="detailButton-content"> <div class="detailButton-content">
<span class="material-icons detailButton-icon check"></span> <span class="material-icons detailButton-icon check"></span>
<div class="detailButton-text button-text"></div>
</div> </div>
</button> </button>
<button is="emby-ratingbutton" type="button" class="button-flat btnUserRating hide detailButton"> <button is="emby-ratingbutton" type="button" class="button-flat btnUserRating hide detailButton" title="${Rate}">
<div class="detailButton-content"> <div class="detailButton-content">
<span class="material-icons detailButton-icon favorite"></span> <span class="material-icons detailButton-icon favorite"></span>
<div class="detailButton-text button-text">${Rate}</div>
</div> </div>
</button> </button>
<button is="emby-button" type="button" class="button-flat btnSplitVersions hide detailButton"> <button is="emby-button" type="button" class="button-flat btnSplitVersions hide detailButton" title="${ButtonSplit}">
<div class="detailButton-content"> <div class="detailButton-content">
<span class="material-icons detailButton-icon call_split"></span> <span class="material-icons detailButton-icon call_split"></span>
<div class="detailButton-text">${ButtonSplit}</div>
</div> </div>
</button> </button>
<button is="emby-button" type="button" class="button-flat btnMoreCommands hide detailButton"> <button is="emby-button" type="button" class="button-flat btnMoreCommands hide detailButton" title="${ButtonMore}">
<div class="detailButton-content"> <div class="detailButton-content">
<span class="material-icons detailButton-icon more_vert"></span> <span class="material-icons detailButton-icon more_vert"></span>
<div class="detailButton-text">${ButtonMore}</div>
</div> </div>
</button> </button>
</div> </div>
@ -110,7 +88,7 @@
<div class="detailPageSecondaryContainer"> <div class="detailPageSecondaryContainer">
<div class="detailImageContainer padded-left"></div> <div class="detailImageContainer padded-left"></div>
<div class="detailPageContent"> <div class="detailPageContent">
<div class="detailPagePrimaryContent padded-left padded-right"> <div class="detailPagePrimaryContent padded-right">
<div class="detailSection"> <div class="detailSection">
<div class="itemMiscInfo nativeName hide"></div> <div class="itemMiscInfo nativeName hide"></div>
@ -124,6 +102,11 @@
<div class="directorsLabel label"></div> <div class="directorsLabel label"></div>
<div class="directors content"></div> <div class="directors content"></div>
</div> </div>
<div class="detailsGroupItem writersGroup hide">
<div class="writersLabel label"></div>
<div class="writers content"></div>
</div>
</div> </div>
<form class="trackSelections hide focuscontainer-x"> <form class="trackSelections hide focuscontainer-x">
@ -164,15 +147,15 @@
</div> </div>
<div class="seriesTimerScheduleSection verticalSection detailVerticalSection hide" style="margin-top:-3em;"> <div class="seriesTimerScheduleSection verticalSection detailVerticalSection hide" style="margin-top:-3em;">
<h2 class="sectionTitle padded-left">${HeaderSchedule}</h2> <h2 class="sectionTitle">${HeaderSchedule}</h2>
<div class="seriesTimerSchedule padded-left padded-right"></div> <div class="seriesTimerSchedule padded-right"></div>
</div> </div>
<div class="collectionItems"></div> <div class="collectionItems hide"></div>
<div class="nextUpSection verticalSection detailVerticalSection hide"> <div class="nextUpSection verticalSection detailVerticalSection hide">
<h2 class="sectionTitle sectionTitle-cards padded-left">${HeaderNextUp}</h2> <h2 class="sectionTitle sectionTitle-cards">${HeaderNextUp}</h2>
<div is="emby-itemscontainer" class="nextUpItems vertical-wrap padded-left padded-right"></div> <div is="emby-itemscontainer" class="nextUpItems vertical-wrap padded-right"></div>
</div> </div>
<div class="programGuideSection hide verticalSection detailVerticalSection"> <div class="programGuideSection hide verticalSection detailVerticalSection">
@ -180,64 +163,64 @@
</div> </div>
<div id="childrenCollapsible" class="hide verticalSection detailVerticalSection"> <div id="childrenCollapsible" class="hide verticalSection detailVerticalSection">
<h2 class="childrenSectionHeader sectionTitle sectionTitle-cards padded-left"> <h2 class="childrenSectionHeader sectionTitle sectionTitle-cards hide">
<span id="childrenTitle"></span> <span id="childrenTitle"></span>
</h2> </h2>
<div id="childrenContent"> <div id="childrenContent">
<div is="emby-itemscontainer" class="childrenItemsContainer itemsContainer padded-left padded-right" style="text-align: left;"></div> <div is="emby-itemscontainer" class="childrenItemsContainer itemsContainer padded-right" style="text-align: left;"></div>
</div> </div>
</div> </div>
<div id="additionalPartsCollapsible" class="verticalSection detailVerticalSection hide"> <div id="additionalPartsCollapsible" class="verticalSection detailVerticalSection hide">
<h2 class="sectionTitle sectionTitle-cards padded-left padded-right">${HeaderAdditionalParts}</h2> <h2 class="sectionTitle sectionTitle-cards padded-right">${HeaderAdditionalParts}</h2>
<div id="additionalPartsContent" is="emby-itemscontainer" class="itemsContainer vertical-wrap padded-left padded-right"></div> <div id="additionalPartsContent" is="emby-itemscontainer" class="itemsContainer vertical-wrap padded-right"></div>
</div> </div>
<div class="verticalSection itemVerticalSection moreFromSeasonSection hide"> <div class="verticalSection detailVerticalSection moreFromSeasonSection hide">
<h2 class="sectionTitle sectionTitle-cards padded-left padded-right"></h2> <h2 class="sectionTitle sectionTitle-cards padded-right"></h2>
<div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-centerfocus="true"> <div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-centerfocus="true">
<div is="emby-itemscontainer" class="scrollSlider focuscontainer-x itemsContainer"></div> <div is="emby-itemscontainer" class="scrollSlider focuscontainer-x itemsContainer"></div>
</div> </div>
</div> </div>
<div class="verticalSection itemVerticalSection moreFromArtistSection hide"> <div class="verticalSection detailVerticalSection moreFromArtistSection hide">
<h2 class="sectionTitle sectionTitle-cards padded-left padded-right"></h2> <h2 class="sectionTitle sectionTitle-cards padded-right"></h2>
<div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-centerfocus="true"> <div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-centerfocus="true">
<div is="emby-itemscontainer" class="scrollSlider focuscontainer-x itemsContainer"></div> <div is="emby-itemscontainer" class="scrollSlider focuscontainer-x itemsContainer"></div>
</div> </div>
</div> </div>
<div id="castCollapsible" class="verticalSection detailVerticalSection hide"> <div id="castCollapsible" class="verticalSection detailVerticalSection hide">
<h2 id="peopleHeader" class="sectionTitle sectionTitle-cards padded-left padded-right">${HeaderCastCrew}</h2> <h2 id="peopleHeader" class="sectionTitle sectionTitle-cards padded-right">${HeaderCastCrew}</h2>
<div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-centerfocus="true"> <div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-centerfocus="true">
<div id="castContent" is="emby-itemscontainer" class="scrollSlider focuscontainer-x itemsContainer"></div> <div id="castContent" is="emby-itemscontainer" class="scrollSlider focuscontainer-x itemsContainer"></div>
</div> </div>
</div> </div>
<div id="seriesScheduleSection" class="verticalSection detailVerticalSection hide"> <div id="seriesScheduleSection" class="verticalSection detailVerticalSection hide">
<h2 class="sectionTitle padded-left padded-right">${HeaderUpcomingOnTV}</h2> <h2 class="sectionTitle padded-right">${HeaderUpcomingOnTV}</h2>
<div id="seriesScheduleList" is="emby-itemscontainer" class="itemsContainer vertical-list padded-left padded-right"></div> <div id="seriesScheduleList" is="emby-itemscontainer" class="itemsContainer vertical-list padded-right"></div>
</div> </div>
<div id="specialsCollapsible" class="verticalSection detailVerticalSection hide"> <div id="specialsCollapsible" class="verticalSection detailVerticalSection hide">
<h2 class="sectionTitle sectionTitle-cards padded-left padded-right">${HeaderSpecialFeatures}</h2> <h2 class="sectionTitle sectionTitle-cards padded-right">${HeaderSpecialFeatures}</h2>
<div id="specialsContent" is="emby-itemscontainer" class="itemsContainer vertical-wrap padded-left padded-right"></div> <div id="specialsContent" is="emby-itemscontainer" class="itemsContainer vertical-wrap padded-right"></div>
</div> </div>
<div id="musicVideosCollapsible" class="verticalSection detailVerticalSection hide"> <div id="musicVideosCollapsible" class="verticalSection detailVerticalSection hide">
<h2 class="sectionTitle sectionTitle-cards padded-left padded-right">${HeaderMusicVideos}</h2> <h2 class="sectionTitle sectionTitle-cards padded-right">${HeaderMusicVideos}</h2>
<div id="musicVideosContent" is="emby-itemscontainer" class="itemsContainer vertical-wrap padded-left padded-right"></div> <div id="musicVideosContent" is="emby-itemscontainer" class="itemsContainer vertical-wrap padded-right"></div>
</div> </div>
<div id="scenesCollapsible" class="verticalSection itemVerticalSection verticalSection-extrabottompadding hide"> <div id="scenesCollapsible" class="verticalSection detailVerticalSection verticalSection-extrabottompadding hide">
<h2 class="sectionTitle sectionTitle-cards padded-left padded-right">${HeaderScenes}</h2> <h2 class="sectionTitle sectionTitle-cards padded-right">${HeaderScenes}</h2>
<div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-centerfocus="true"> <div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-centerfocus="true">
<div id="scenesContent" is="emby-itemscontainer" class="scrollSlider focuscontainer-x itemsContainer"></div> <div id="scenesContent" is="emby-itemscontainer" class="scrollSlider focuscontainer-x itemsContainer"></div>
</div> </div>
</div> </div>
<div id="similarCollapsible" class="verticalSection itemVerticalSection verticalSection-extrabottompadding hide"> <div id="similarCollapsible" class="verticalSection detailVerticalSection verticalSection-extrabottompadding hide">
<h2 class="sectionTitle sectionTitle-cards padded-left padded-right">${HeaderMoreLikeThis}</h2> <h2 class="sectionTitle sectionTitle-cards padded-right">${HeaderMoreLikeThis}</h2>
<div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-centerfocus="true"> <div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-centerfocus="true">
<div is="emby-itemscontainer" class="scrollSlider focuscontainer-x itemsContainer similarContent"></div> <div is="emby-itemscontainer" class="scrollSlider focuscontainer-x itemsContainer similarContent"></div>
</div> </div>

View File

@ -28,15 +28,11 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
} }
function hideAll(page, className, show) { function hideAll(page, className, show) {
var i; for (const elem of page.querySelectorAll('.' + className)) {
var length;
var elems = page.querySelectorAll('.' + className);
for (i = 0, length = elems.length; i < length; i++) {
if (show) { if (show) {
elems[i].classList.remove('hide'); elem.classList.remove('hide');
} else { } else {
elems[i].classList.add('hide'); elem.classList.add('hide');
} }
} }
} }
@ -51,7 +47,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
positionTo: button, positionTo: button,
cancelTimer: false, cancelTimer: false,
record: false, record: false,
deleteItem: true === item.IsFolder, deleteItem: item.CanDelete === true,
shuffle: false, shuffle: false,
instantMix: false, instantMix: false,
user: user, user: user,
@ -75,7 +71,9 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
moreButton: false, moreButton: false,
recordButton: false recordButton: false
}); });
return html += '</div>'; html += '</div>';
return html;
} }
function renderSeriesTimerSchedule(page, apiClient, seriesTimerId) { function renderSeriesTimerSchedule(page, apiClient, seriesTimerId) {
@ -143,9 +141,13 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
var mediaSources = item.MediaSources; var mediaSources = item.MediaSources;
instance._currentPlaybackMediaSources = mediaSources; instance._currentPlaybackMediaSources = mediaSources;
page.querySelector('.trackSelections').classList.remove('hide'); page.querySelector('.trackSelections').classList.remove('hide');
select.setLabel(globalize.translate('LabelVersion')); select.setLabel(globalize.translate('LabelVersion'));
var currentValue = select.value; var currentValue = select.value;
var selectedId = mediaSources[0].Id; var selectedId = mediaSources[0].Id;
select.innerHTML = mediaSources.map(function (v) { select.innerHTML = mediaSources.map(function (v) {
var selected = v.Id === selectedId ? ' selected' : ''; var selected = v.Id === selectedId ? ' selected' : '';
@ -172,7 +174,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
return m.Id === mediaSourceId; return m.Id === mediaSourceId;
})[0]; })[0];
var tracks = mediaSource.MediaStreams.filter(function (m) { var tracks = mediaSource.MediaStreams.filter(function (m) {
return 'Video' === m.Type; return m.Type === 'Video';
}); });
var select = page.querySelector('.selectVideo'); var select = page.querySelector('.selectVideo');
select.setLabel(globalize.translate('LabelVideo')); select.setLabel(globalize.translate('LabelVideo'));
@ -242,12 +244,24 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
select.setLabel(globalize.translate('LabelSubtitles')); select.setLabel(globalize.translate('LabelSubtitles'));
var selectedId = null == mediaSource.DefaultSubtitleStreamIndex ? -1 : mediaSource.DefaultSubtitleStreamIndex; var selectedId = null == mediaSource.DefaultSubtitleStreamIndex ? -1 : mediaSource.DefaultSubtitleStreamIndex;
if (tracks.length) { var videoTracks = mediaSource.MediaStreams.filter(function (m) {
return 'Video' === m.Type;
});
// This only makes sence on Video items
if (videoTracks.length) {
var selected = -1 === selectedId ? ' selected' : ''; var selected = -1 === selectedId ? ' selected' : '';
select.innerHTML = '<option value="-1">' + globalize.translate('Off') + '</option>' + tracks.map(function (v) { select.innerHTML = '<option value="-1">' + globalize.translate('Off') + '</option>' + tracks.map(function (v) {
selected = v.Index === selectedId ? ' selected' : ''; selected = v.Index === selectedId ? ' selected' : '';
return '<option value="' + v.Index + '" ' + selected + '>' + v.DisplayTitle + '</option>'; return '<option value="' + v.Index + '" ' + selected + '>' + v.DisplayTitle + '</option>';
}).join(''); }).join('');
if (tracks.length > 1) {
select.removeAttribute('disabled');
} else {
select.setAttribute('disabled', 'disabled');
}
page.querySelector('.selectSubtitlesContainer').classList.remove('hide'); page.querySelector('.selectSubtitlesContainer').classList.remove('hide');
} else { } else {
select.innerHTML = ''; select.innerHTML = '';
@ -278,7 +292,15 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
var enableShuffle = item.IsFolder || -1 !== ['MusicAlbum', 'MusicGenre', 'MusicArtist'].indexOf(item.Type); var enableShuffle = item.IsFolder || -1 !== ['MusicAlbum', 'MusicGenre', 'MusicArtist'].indexOf(item.Type);
hideAll(page, 'btnShuffle', enableShuffle); hideAll(page, 'btnShuffle', enableShuffle);
canPlay = true; canPlay = true;
hideAll(page, 'btnResume', item.UserData && item.UserData.PlaybackPositionTicks > 0);
const isResumable = item.UserData && item.UserData.PlaybackPositionTicks > 0;
hideAll(page, 'btnResume', isResumable);
if (isResumable) {
for (const elem of page.querySelectorAll('.btnPlay')) {
elem.querySelector('.detailButton-icon').classList.replace('play_arrow', 'replay');
}
}
} else { } else {
hideAll(page, 'btnPlay'); hideAll(page, 'btnPlay');
hideAll(page, 'btnResume'); hideAll(page, 'btnResume');
@ -324,8 +346,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
function getArtistLinksHtml(artists, serverId, context) { function getArtistLinksHtml(artists, serverId, context) {
var html = []; var html = [];
for (var i = 0, length = artists.length; i < length; i++) { for (const artist of artists) {
var artist = artists[i];
var href = appRouter.getRouteUrl(artist, { var href = appRouter.getRouteUrl(artist, {
context: context, context: context,
itemType: 'MusicArtist', itemType: 'MusicArtist',
@ -333,10 +354,18 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
}); });
html.push('<a style="color:inherit;" class="button-link" is="emby-linkbutton" href="' + href + '">' + artist.Name + '</a>'); html.push('<a style="color:inherit;" class="button-link" is="emby-linkbutton" href="' + href + '">' + artist.Name + '</a>');
} }
html = html.join(' / ');
return html = html.join(' / '); return html;
} }
function renderName(item, container, isStatic, context) {
/**
* Renders 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 parentRoute;
var parentNameHtml = []; var parentNameHtml = [];
var parentNameLast = false; var parentNameLast = false;
@ -410,16 +439,12 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
if (parentNameLast) { if (parentNameLast) {
// Music // Music
if (layoutManager.mobile) { if (layoutManager.mobile) {
html = '<h3 class="parentName" style="margin: .25em 0;">' + parentNameHtml.join('</br>') + '</h3>'; html = '<h3 class="parentName musicParentName">' + parentNameHtml.join('</br>') + '</h3>';
} else { } else {
html = '<h3 class="parentName" style="margin: .25em 0;">' + parentNameHtml.join(' - ') + '</h3>'; html = '<h3 class="parentName musicParentName">' + parentNameHtml.join(' - ') + '</h3>';
} }
} else { } else {
if (layoutManager.mobile) { html = '<h1 class="parentName">' + tvShowHtml + '</h1>';
html = '<h1 class="parentName" style="margin: 0.2em 0 0">' + parentNameHtml.join('</br>') + '</h1>';
} else {
html = '<h1 class="parentName" style="margin: 0.2em 0 0">' + tvShowHtml + '</h1>';
}
} }
} }
@ -428,17 +453,19 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
}); });
if (html && !parentNameLast) { if (html && !parentNameLast) {
if (!layoutManager.mobile && tvSeasonHtml) { if (tvSeasonHtml) {
html += '<h3 class="itemName infoText" style="margin: 0.2em 0 0">' + tvSeasonHtml + ' - ' + name + '</h3>'; html += '<h3 class="itemName infoText subtitle">' + tvSeasonHtml + ' - ' + name + '</h3>';
} else { } else {
html += '<h3 class="itemName infoText" style="margin: 0.2em 0 0">' + name + '</h3>'; html += '<h3 class="itemName infoText subtitle">' + name + '</h3>';
} }
} else if (item.OriginalTitle && item.OriginalTitle != item.Name) {
html = '<h1 class="itemName infoText parentNameLast withOriginalTitle">' + name + '</h1>' + html;
} else { } else {
html = '<h1 class="itemName infoText" style="margin: 0.4em 0 0">' + name + '</h1>' + html; html = '<h1 class="itemName infoText parentNameLast">' + name + '</h1>' + html;
} }
if (item.OriginalTitle && item.OriginalTitle != item.Name) { if (item.OriginalTitle && item.OriginalTitle != item.Name) {
html += '<h4 class="itemName infoText" style="margin: 0 0 0;">' + item.OriginalTitle + '</h4>'; html += '<h4 class="itemName infoText originalTitle">' + item.OriginalTitle + '</h4>';
} }
container.innerHTML = html; container.innerHTML = html;
@ -470,43 +497,18 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
var imgUrl; var imgUrl;
var hasbackdrop = false; var hasbackdrop = false;
var itemBackdropElement = page.querySelector('#itemBackdrop'); 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.detailsBanner()) {
return false; return false;
} }
if ('Program' === item.Type && item.ImageTags && item.ImageTags.Thumb) { if (item.BackdropImageTags && item.BackdropImageTags.length) {
imgUrl = apiClient.getScaledImageUrl(item.Id, {
type: 'Thumb',
maxWidth: dom.getScreenWidth(),
index: 0,
tag: item.ImageTags.Thumb
});
page.classList.remove('noBackdrop');
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
});
page.classList.remove('noBackdrop');
imageLoader.lazyImage(itemBackdropElement, imgUrl);
hasbackdrop = true;
} else if (item.BackdropImageTags && item.BackdropImageTags.length) {
imgUrl = apiClient.getScaledImageUrl(item.Id, { imgUrl = apiClient.getScaledImageUrl(item.Id, {
type: 'Backdrop', type: 'Backdrop',
maxWidth: dom.getScreenWidth(), maxWidth: dom.getScreenWidth(),
index: 0, index: 0,
tag: item.BackdropImageTags[0] tag: item.BackdropImageTags[0]
}); });
page.classList.remove('noBackdrop');
imageLoader.lazyImage(itemBackdropElement, imgUrl); imageLoader.lazyImage(itemBackdropElement, imgUrl);
hasbackdrop = true; hasbackdrop = true;
} else if (item.ParentBackdropItemId && item.ParentBackdropImageTags && item.ParentBackdropImageTags.length) { } else if (item.ParentBackdropItemId && item.ParentBackdropImageTags && item.ParentBackdropImageTags.length) {
@ -516,50 +518,35 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
index: 0, index: 0,
tag: item.ParentBackdropImageTags[0] tag: item.ParentBackdropImageTags[0]
}); });
page.classList.remove('noBackdrop');
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
});
page.classList.remove('noBackdrop');
imageLoader.lazyImage(itemBackdropElement, imgUrl); imageLoader.lazyImage(itemBackdropElement, imgUrl);
hasbackdrop = true; hasbackdrop = true;
} else { } else {
itemBackdropElement.style.backgroundImage = ''; itemBackdropElement.style.backgroundImage = '';
} }
if ('Person' === item.Type) {
// FIXME: This hides the backdrop on all persons to fix a margin issue. Ideally, a proper fix should be made.
page.classList.add('noBackdrop');
itemBackdropElement.classList.add('personBackdrop');
} else {
itemBackdropElement.classList.remove('personBackdrop');
}
return hasbackdrop; return hasbackdrop;
} }
function reloadFromItem(instance, page, params, item, user) { function reloadFromItem(instance, page, params, item, user) {
var context = params.context; const apiClient = connectionManager.getApiClient(item.ServerId);
page.querySelector('.detailPagePrimaryContainer').classList.add('detailSticky');
renderName(item, page.querySelector('.nameContainer'), false, context);
var apiClient = connectionManager.getApiClient(item.ServerId);
renderSeriesTimerEditor(page, item, apiClient, user);
renderTimerEditor(page, item, apiClient, user);
renderImage(page, item, apiClient, user);
renderLogo(page, item, apiClient);
Emby.Page.setTitle(''); Emby.Page.setTitle('');
setInitialCollapsibleState(page, item, apiClient, context, user);
renderDetails(page, item, apiClient, context); // Start rendering the artwork first
renderTrackSelections(page, instance, item); renderImage(page, item);
renderLogo(page, item, apiClient);
renderBackdrop(item); renderBackdrop(item);
renderDetailPageBackdrop(page, item, apiClient); 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); var canPlay = reloadPlayButtons(page, item);
if ((item.LocalTrailerCount || item.RemoteTrailers && item.RemoteTrailers.length) && -1 !== playbackManager.getSupportedCommands().indexOf('PlayTrailers')) { if ((item.LocalTrailerCount || item.RemoteTrailers && item.RemoteTrailers.length) && -1 !== playbackManager.getSupportedCommands().indexOf('PlayTrailers')) {
@ -570,12 +557,6 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
setTrailerButtonVisibility(page, item); setTrailerButtonVisibility(page, item);
if (item.CanDelete && !item.IsFolder) {
hideAll(page, 'btnDeleteItem', true);
} else {
hideAll(page, 'btnDeleteItem');
}
if ('Program' !== item.Type || canPlay) { if ('Program' !== item.Type || canPlay) {
hideAll(page, 'mainDetailButtons', true); hideAll(page, 'mainDetailButtons', true);
} else { } else {
@ -667,18 +648,15 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
} }
function renderLogo(page, item, apiClient) { function renderLogo(page, item, apiClient) {
var url = logoImageUrl(item, apiClient, {
maxWidth: 400
});
var detailLogo = page.querySelector('.detailLogo'); var detailLogo = page.querySelector('.detailLogo');
var url = logoImageUrl(item, apiClient, {});
if (!layoutManager.mobile && !userSettings.enableBackdrops()) { if (!layoutManager.mobile && !userSettings.enableBackdrops()) {
detailLogo.classList.add('hide'); detailLogo.classList.add('hide');
} else if (url) { } else if (url) {
detailLogo.classList.remove('hide'); detailLogo.classList.remove('hide');
detailLogo.classList.add('lazy'); imageLoader.setLazyImage(detailLogo, url);
detailLogo.setAttribute('data-src', url);
imageLoader.lazyImage(detailLogo);
} else { } else {
detailLogo.classList.add('hide'); detailLogo.classList.add('hide');
} }
@ -704,172 +682,60 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
} }
} }
function renderLinks(linksElem, item) { function renderLinks(page, item) {
var html = []; var externalLinksElem = page.querySelector('.itemExternalLinks');
var links = []; var links = [];
if (!layoutManager.tv && item.HomePageUrl) { 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) { if (item.ExternalUrls) {
for (var i = 0, length = item.ExternalUrls.length; i < length; i++) { for (const url of item.ExternalUrls) {
var url = item.ExternalUrls[i]; links.push(`<a is="emby-linkbutton" class="button-link" href="${url.Url}" target="_blank">${url.Name}</a>`);
links.push('<a style="color:inherit;" is="emby-linkbutton" class="button-link" href="' + url.Url + '" target="_blank">' + url.Name + '</a>');
} }
} }
var html = [];
if (links.length) { if (links.length) {
html.push(links.join(', ')); html.push(links.join(', '));
} }
linksElem.innerHTML = html.join(', '); externalLinksElem.innerHTML = html.join(', ');
if (html.length) { if (html.length) {
linksElem.classList.remove('hide'); externalLinksElem.classList.remove('hide');
} else { } else {
linksElem.classList.add('hide'); externalLinksElem.classList.add('hide');
} }
} }
function renderDetailImage(page, elem, item, apiClient, editable, imageLoader, indicators) { function renderDetailImage(elem, item, imageLoader) {
if ('SeriesTimer' === item.Type || 'Program' === item.Type) { const itemArray = [];
editable = false; 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
});
elem.classList.add('detailimg-hidemobile'); elem.innerHTML = cardHtml;
var imageTags = item.ImageTags || {}; imageLoader.lazyChildren(elem);
if (item.PrimaryImageTag) {
imageTags.Primary = item.PrimaryImageTag;
}
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 += "<a class='itemDetailGalleryLink itemDetailImage defaultCardBackground defaultCardBackground" + cardBuilder.getDefaultBackgroundClass(item.Name) + "' is='emby-linkbutton' style='display:block;margin:0;padding:0;' href='#'>";
} else if (!editable && url === undefined) {
html += "<div class='itemDetailGalleryLink itemDetailImage defaultCardBackground defaultCardBackground" + cardBuilder.getDefaultBackgroundClass(item.Name) + "' is='emby-linkbutton' style='display:block;margin:0;padding:0;' href='#'>";
} else if (editable) {
html += "<a class='itemDetailGalleryLink' is='emby-linkbutton' style='display:block;margin:0;padding:0;' href='#'>";
}
if (url) {
html += "<img class='itemDetailImage lazy' src='data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=' />";
}
if (url === undefined) {
html += cardBuilder.getDefaultText(item);
}
if (editable) {
html += '</a>';
} else if (!editable && url === undefined) {
html += '</div>';
}
var progressHtml = item.IsFolder || !item.UserData ? '' : indicators.getProgressBarHtml(item);
html += '<div class="detailImageProgressContainer">';
if (progressHtml) {
html += progressHtml;
}
html += '</div>';
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);
}
} }
function renderImage(page, item, apiClient, user) { function renderImage(page, item) {
renderDetailImage( renderDetailImage(
page,
page.querySelector('.detailImageContainer'), page.querySelector('.detailImageContainer'),
item, item,
apiClient, imageLoader
user.Policy.IsAdministrator && 'Photo' != item.MediaType,
imageLoader,
indicators
); );
} }
@ -985,54 +851,41 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
} }
} }
function renderOverview(elems, item) { function renderOverview(page, item) {
for (var i = 0, length = elems.length; i < length; i++) { for (const overviewElemnt of page.querySelectorAll('.overview')) {
var elem = elems[i];
var overview = item.Overview || ''; var overview = item.Overview || '';
if (overview) { if (overview) {
elem.innerHTML = overview; overviewElemnt.innerHTML = overview;
elem.classList.remove('hide'); overviewElemnt.classList.remove('hide');
elem.classList.add('detail-clamp-text'); overviewElemnt.classList.add('detail-clamp-text');
// Grab the sibling element to control the expand state // 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 // Detect if we have overflow of text. Based on this StackOverflow answer
// https://stackoverflow.com/a/35157976 // 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'); expandButton.classList.remove('hide');
} else { } else {
expandButton.classList.add('hide'); expandButton.classList.add('hide');
} }
expandButton.addEventListener('click', toggleLineClamp.bind(null, elem)); expandButton.addEventListener('click', toggleLineClamp.bind(null, overviewElemnt));
var anchors = elem.querySelectorAll('a'); for (const anchor of overviewElemnt.querySelectorAll('a')) {
anchor.setAttribute('target', '_blank');
for (var j = 0, length2 = anchors.length; j < length2; j++) {
anchors[j].setAttribute('target', '_blank');
} }
} else { } else {
elem.innerHTML = ''; overviewElemnt.innerHTML = '';
elem.classList.add('hide'); overviewElemnt.classList.add('hide');
} }
} }
} }
function renderGenres(page, item, context) { function renderGenres(page, item, context = inferContext(item)) {
context = context || inferContext(item);
var type;
var genres = item.GenreItems || []; var genres = item.GenreItems || [];
var type = context === 'music' ? 'MusicGenre' : 'Genre';
switch (context) {
case 'music':
type = 'MusicGenre';
break;
default:
type = 'Genre';
}
var html = genres.map(function (p) { var html = genres.map(function (p) {
return '<a style="color:inherit;" class="button-link" is="emby-linkbutton" href="' + appRouter.getRouteUrl({ return '<a style="color:inherit;" class="button-link" is="emby-linkbutton" href="' + appRouter.getRouteUrl({
@ -1058,19 +911,49 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
} }
} }
function renderDirector(page, item, context) { function renderWriter(page, item, context) {
var directors = (item.People || []).filter(function (p) { var writers = (item.People || []).filter(function (person) {
return 'Director' === p.Type; return person.Type === 'Writer';
}); });
var html = directors.map(function (p) {
var html = writers.map(function (person) {
return '<a style="color:inherit;" class="button-link" is="emby-linkbutton" href="' + appRouter.getRouteUrl({ return '<a style="color:inherit;" class="button-link" is="emby-linkbutton" href="' + appRouter.getRouteUrl({
Name: p.Name, Name: person.Name,
Type: 'Person', Type: 'Person',
ServerId: item.ServerId, ServerId: item.ServerId,
Id: p.Id Id: person.Id
}, { }, {
context: context context: context
}) + '">' + p.Name + '</a>'; }) + '">' + person.Name + '</a>';
}).join(', ');
var writersLabel = page.querySelector('.writersLabel');
writersLabel.innerHTML = globalize.translate(writers.length > 1 ? 'Writers' : 'Writer');
var writersValue = page.querySelector('.writers');
writersValue.innerHTML = html;
var writersGroup = page.querySelector('.writersGroup');
if (writers.length) {
writersGroup.classList.remove('hide');
} else {
writersGroup.classList.add('hide');
}
}
function renderDirector(page, item, context) {
var directors = (item.People || []).filter(function (person) {
return person.Type === 'Director';
});
var html = directors.map(function (person) {
return '<a style="color:inherit;" class="button-link" is="emby-linkbutton" href="' + appRouter.getRouteUrl({
Name: person.Name,
Type: 'Person',
ServerId: item.ServerId,
Id: person.Id
}, {
context: context
}) + '">' + person.Name + '</a>';
}).join(', '); }).join(', ');
var directorsLabel = page.querySelector('.directorsLabel'); var directorsLabel = page.querySelector('.directorsLabel');
@ -1086,13 +969,39 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
} }
} }
function renderDetails(page, item, apiClient, context, isStatic) { function renderMiscInfo(page, item) {
renderSimilarItems(page, item, context); const primaryItemMiscInfo = page.querySelectorAll('.itemMiscInfo-primary');
renderMoreFromSeason(page, item, apiClient);
renderMoreFromArtist(page, item, apiClient); for (const miscInfo of primaryItemMiscInfo) {
renderDirector(page, item, context); mediaInfo.fillPrimaryMediaInfo(miscInfo, item, {
renderGenres(page, item, context); interactive: true,
renderChannelGuide(page, apiClient, item); 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 (const 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'); var taglineElement = page.querySelector('.tagline');
if (item.Taglines && item.Taglines.length) { if (item.Taglines && item.Taglines.length) {
@ -1101,44 +1010,21 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
} else { } else {
taglineElement.classList.add('hide'); taglineElement.classList.add('hide');
} }
}
var overview = page.querySelector('.overview'); function renderDetails(page, item, apiClient, context, isStatic) {
var externalLinksElem = page.querySelector('.itemExternalLinks'); renderSimilarItems(page, item, context);
renderMoreFromSeason(page, item, apiClient);
renderOverview([overview], item); renderMoreFromArtist(page, item, apiClient);
renderDirector(page, item, context);
var i; renderWriter(page, item, context);
var itemMiscInfo; renderGenres(page, item, context);
itemMiscInfo = page.querySelectorAll('.itemMiscInfo-primary'); renderChannelGuide(page, apiClient, item);
for (i = 0; i < itemMiscInfo.length; i++) { renderTagline(page, item);
mediaInfo.fillPrimaryMediaInfo(itemMiscInfo[i], item, { renderOverview(page, item);
interactive: true, renderMiscInfo(page, item);
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');
}
}
reloadUserDataButtons(page, item); reloadUserDataButtons(page, item);
renderLinks(externalLinksElem, item); renderLinks(page, item);
renderTags(page, item); renderTags(page, item);
renderSeriesAirTime(page, item, isStatic); renderSeriesAirTime(page, item, isStatic);
} }
@ -1426,8 +1312,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
action: 'playallfromhere', action: 'playallfromhere',
image: false, image: false,
artist: 'auto', artist: 'auto',
containerAlbumArtists: item.AlbumArtists, containerAlbumArtists: item.AlbumArtists
addToListButton: true
}); });
isList = true; isList = true;
} else if ('Series' == item.Type) { } else if ('Series' == item.Type) {
@ -1469,11 +1354,12 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
items: result.Items, items: result.Items,
showIndexNumber: false, showIndexNumber: false,
enableOverview: true, enableOverview: true,
enablePlayedButton: layoutManager.mobile ? false : true,
infoButton: layoutManager.mobile ? false : true,
imageSize: 'large', imageSize: 'large',
enableSideMediaInfo: false, enableSideMediaInfo: false,
highlight: false, highlight: false,
action: layoutManager.tv ? 'resume' : 'none', action: layoutManager.tv ? 'resume' : 'none',
infoButton: true,
imagePlayButton: true, imagePlayButton: true,
includeParentInfoInTitle: false includeParentInfoInTitle: false
}); });
@ -1500,6 +1386,9 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
childrenItemsContainer.classList.remove('vertical-list'); childrenItemsContainer.classList.remove('vertical-list');
} }
} }
if (layoutManager.mobile) {
childrenItemsContainer.classList.remove('padded-right');
}
childrenItemsContainer.innerHTML = html; childrenItemsContainer.innerHTML = html;
imageLoader.lazyChildren(childrenItemsContainer); imageLoader.lazyChildren(childrenItemsContainer);
if ('BoxSet' == item.Type) { if ('BoxSet' == item.Type) {
@ -1701,12 +1590,10 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
} }
function renderCollectionItems(page, parentItem, types, items) { function renderCollectionItems(page, parentItem, types, items) {
page.querySelector('.collectionItems').classList.remove('hide');
page.querySelector('.collectionItems').innerHTML = ''; page.querySelector('.collectionItems').innerHTML = '';
var i;
var length;
for (i = 0, length = types.length; i < length; i++) { for (const type of types) {
var type = types[i];
var typeItems = filterItemsByCollectionItemType(items, type); var typeItems = filterItemsByCollectionItemType(items, type);
if (typeItems.length) { if (typeItems.length) {
@ -1739,8 +1626,8 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
renderChildren(page, parentItem); renderChildren(page, parentItem);
}; };
for (i = 0, length = containers.length; i < length; i++) { for (const container of containers) {
containers[i].notifyRefreshNeeded = notifyRefreshNeeded; container.notifyRefreshNeeded = notifyRefreshNeeded;
} }
// if nothing in the collection can be played hide play and shuffle buttons // if nothing in the collection can be played hide play and shuffle buttons
@ -1876,7 +1763,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
function renderCast(page, item) { function renderCast(page, item) {
var people = (item.People || []).filter(function (p) { var people = (item.People || []).filter(function (p) {
return 'Director' !== p.Type; return p.Type === 'Actor';
}); });
if (!people.length) { if (!people.length) {
@ -1905,12 +1792,10 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
} }
function bindAll(view, selector, eventName, fn) { function bindAll(view, selector, eventName, fn) {
var i;
var length;
var elems = view.querySelectorAll(selector); var elems = view.querySelectorAll(selector);
for (i = 0, length = elems.length; i < length; i++) { for (const elem of elems) {
elems[i].addEventListener(eventName, fn); elem.addEventListener(eventName, fn);
} }
} }
@ -1923,13 +1808,14 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
return function (view, params) { return function (view, params) {
function reload(instance, page, params) { function reload(instance, page, params) {
loading.show(); loading.show();
var apiClient = params.serverId ? connectionManager.getApiClient(params.serverId) : ApiClient; var apiClient = params.serverId ? connectionManager.getApiClient(params.serverId) : ApiClient;
var promises = [getPromise(apiClient, params), apiClient.getCurrentUser()];
Promise.all(promises).then(function (responses) { Promise.all([getPromise(apiClient, params), apiClient.getCurrentUser()]).then(([item, user]) => {
var item = responses[0];
var user = responses[1];
currentItem = item; currentItem = item;
reloadFromItem(instance, page, params, item, user); reloadFromItem(instance, page, params, item, user);
}).catch((error) => {
console.error('failed to get item or current user: ', error);
}); });
} }
@ -1980,7 +1866,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
}); });
} }
playItem(item, item.UserData && 'resume' === mode ? item.UserData.PlaybackPositionTicks : 0); playItem(item, item.UserData && mode === 'resume' ? item.UserData.PlaybackPositionTicks : 0);
} }
function onPlayClick() { function onPlayClick() {
@ -1995,15 +1881,6 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
playbackManager.shuffle(currentItem); playbackManager.shuffle(currentItem);
} }
function onDeleteClick() {
require(['deleteHelper'], function (deleteHelper) {
deleteHelper.deleteItem({
item: currentItem,
navigate: true
});
});
}
function onCancelSeriesTimerClick() { function onCancelSeriesTimerClick() {
require(['recordingHelper'], function (recordingHelper) { require(['recordingHelper'], function (recordingHelper) {
recordingHelper.cancelSeriesTimerWithConfirmation(currentItem.Id, currentItem.ServerId).then(function () { recordingHelper.cancelSeriesTimerWithConfirmation(currentItem.Id, currentItem.ServerId).then(function () {
@ -2092,7 +1969,6 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
bindAll(view, '.btnPlayTrailer', 'click', onPlayTrailerClick); bindAll(view, '.btnPlayTrailer', 'click', onPlayTrailerClick);
bindAll(view, '.btnCancelSeriesTimer', 'click', onCancelSeriesTimerClick); bindAll(view, '.btnCancelSeriesTimer', 'click', onCancelSeriesTimerClick);
bindAll(view, '.btnCancelTimer', 'click', onCancelTimerClick); bindAll(view, '.btnCancelTimer', 'click', onCancelTimerClick);
bindAll(view, '.btnDeleteItem', 'click', onDeleteClick);
bindAll(view, '.btnDownload', 'click', onDownloadClick); bindAll(view, '.btnDownload', 'click', onDownloadClick);
view.querySelector('.trackSelections').addEventListener('submit', onTrackSelectionsSubmit); view.querySelector('.trackSelections').addEventListener('submit', onTrackSelectionsSubmit);
view.querySelector('.btnSplitVersions').addEventListener('click', function () { view.querySelector('.btnSplitVersions').addEventListener('click', function () {
@ -2125,9 +2001,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
view.addEventListener('viewshow', function (e) { view.addEventListener('viewshow', function (e) {
var page = this; var page = this;
if (layoutManager.mobile) { libraryMenu.setTransparentMenu(true);
libraryMenu.setTransparentMenu(true);
}
if (e.detail.isRestored) { if (e.detail.isRestored) {
if (currentItem) { if (currentItem) {

View File

@ -6,7 +6,7 @@
justify-content: center; justify-content: center;
min-width: 104px; min-width: 104px;
min-height: 24px; min-height: 24px;
padding-top: 1.25em; padding-top: 0.85em;
z-index: 1; z-index: 1;
color: #fff; color: #fff;
display: flex; display: flex;

View File

@ -211,7 +211,7 @@
'MozAnimation': 'animationend', 'MozAnimation': 'animationend',
'WebkitAnimation': 'webkitAnimationEnd' 'WebkitAnimation': 'webkitAnimationEnd'
}; };
for (let t in animations) { for (const t in animations) {
if (el.style[t] !== undefined) { if (el.style[t] !== undefined) {
_animationEvent = animations[t]; _animationEvent = animations[t];
return animations[t]; return animations[t];
@ -251,7 +251,7 @@
'MozTransition': 'transitionend', 'MozTransition': 'transitionend',
'WebkitTransition': 'webkitTransitionEnd' 'WebkitTransition': 'webkitTransitionEnd'
}; };
for (let t in transitions) { for (const t in transitions) {
if (el.style[t] !== undefined) { if (el.style[t] !== undefined) {
_transitionEvent = transitions[t]; _transitionEvent = transitions[t];
return transitions[t]; return transitions[t];

View File

@ -71,12 +71,12 @@ define(['connectionManager', 'listView', 'cardBuilder', 'imageLoader', 'libraryB
html += '<div class="' + sectionClass + '" data-type="' + section.type + '">'; html += '<div class="' + sectionClass + '" data-type="' + section.type + '">';
html += '<div class="sectionTitleContainer sectionTitleContainer-cards">'; html += '<div class="sectionTitleContainer sectionTitleContainer-cards">';
html += '<h2 class="sectionTitle sectionTitle-cards padded-left">'; html += '<h2 class="sectionTitle sectionTitle-cards">';
html += section.name; html += section.name;
html += '</h2>'; html += '</h2>';
html += '<a is="emby-linkbutton" href="#" class="clearLink hide" style="margin-left:1em;vertical-align:middle;"><button is="emby-button" type="button" class="raised more raised-mini noIcon">' + globalize.translate('ButtonMore') + '</button></a>'; html += '<a is="emby-linkbutton" href="#" class="clearLink hide" style="margin-left:1em;vertical-align:middle;"><button is="emby-button" type="button" class="raised more raised-mini noIcon">' + globalize.translate('ButtonMore') + '</button></a>';
html += '</div>'; html += '</div>';
html += '<div is="emby-itemscontainer" class="itemsContainer padded-left padded-right">'; html += '<div is="emby-itemscontainer" class="itemsContainer padded-right">';
html += '</div>'; html += '</div>';
return html += '</div>'; return html += '</div>';
}).join(''); }).join('');

View File

@ -15,7 +15,7 @@ define([
'detailtablecss'], function () { 'detailtablecss'], function () {
function defineRoute(newRoute) { function defineRoute(newRoute) {
var path = newRoute.path; var path = newRoute.alias ? newRoute.alias : newRoute.path;
console.debug('defining route: ' + path); console.debug('defining route: ' + path);
newRoute.dictionary = 'core'; newRoute.dictionary = 'core';
Emby.Page.addRoute(path, newRoute); Emby.Page.addRoute(path, newRoute);
@ -240,8 +240,9 @@ define([
transition: 'fade' transition: 'fade'
}); });
defineRoute({ defineRoute({
path: '/itemdetails.html', alias: '/details',
controller: 'itemDetails', path: '/controllers/itemDetails/index.html',
controller: 'itemDetails/index',
autoFocus: false, autoFocus: false,
transition: 'fade' transition: 'fade'
}); });

View File

@ -1038,7 +1038,7 @@ var AppInfo = {};
} }
if ('SeriesTimer' == itemType) { if ('SeriesTimer' == itemType) {
return 'itemdetails.html?seriesTimerId=' + id + '&serverId=' + serverId; return 'details?seriesTimerId=' + id + '&serverId=' + serverId;
} }
if ('livetv' == item.CollectionType) { if ('livetv' == item.CollectionType) {
@ -1108,13 +1108,13 @@ var AppInfo = {};
var itemTypes = ['Playlist', 'TvChannel', 'Program', 'BoxSet', 'MusicAlbum', 'MusicGenre', 'Person', 'Recording', 'MusicArtist']; var itemTypes = ['Playlist', 'TvChannel', 'Program', 'BoxSet', 'MusicAlbum', 'MusicGenre', 'Person', 'Recording', 'MusicArtist'];
if (itemTypes.indexOf(itemType) >= 0) { if (itemTypes.indexOf(itemType) >= 0) {
return 'itemdetails.html?id=' + id + '&serverId=' + serverId; return 'details?id=' + id + '&serverId=' + serverId;
} }
var contextSuffix = context ? '&context=' + context : ''; var contextSuffix = context ? '&context=' + context : '';
if ('Series' == itemType || 'Season' == itemType || 'Episode' == itemType) { if ('Series' == itemType || 'Season' == itemType || 'Episode' == itemType) {
return 'itemdetails.html?id=' + id + contextSuffix + '&serverId=' + serverId; return 'details?id=' + id + contextSuffix + '&serverId=' + serverId;
} }
if (item.IsFolder) { if (item.IsFolder) {
@ -1125,7 +1125,7 @@ var AppInfo = {};
return '#'; return '#';
} }
return 'itemdetails.html?id=' + id + '&serverId=' + serverId; return 'details?id=' + id + '&serverId=' + serverId;
}; };
appRouter.showItem = showItem; appRouter.showItem = showItem;

View File

@ -1535,6 +1535,7 @@
"Whitelist": "Whitelist", "Whitelist": "Whitelist",
"WizardCompleted": "That's all we need for now. Jellyfin has begun collecting information about your media library. Check out some of our apps, and then click <b>Finish</b> to view the <b>Dashboard</b>.", "WizardCompleted": "That's all we need for now. Jellyfin has begun collecting information about your media library. Check out some of our apps, and then click <b>Finish</b> to view the <b>Dashboard</b>.",
"Writer": "Writer", "Writer": "Writer",
"Writers": "Writers",
"XmlDocumentAttributeListHelp": "These attributes are applied to the root element of every XML response.", "XmlDocumentAttributeListHelp": "These attributes are applied to the root element of every XML response.",
"XmlTvKidsCategoriesHelp": "Programs with these categories will be displayed as programs for children. Separate multiple with '|'.", "XmlTvKidsCategoriesHelp": "Programs with these categories will be displayed as programs for children. Separate multiple with '|'.",
"XmlTvMovieCategoriesHelp": "Programs with these categories will be displayed as movies. Separate multiple with '|'.", "XmlTvMovieCategoriesHelp": "Programs with these categories will be displayed as movies. Separate multiple with '|'.",

View File

@ -227,7 +227,7 @@ html {
color: #fff !important; color: #fff !important;
} }
.detailSticky { .detailRibbon {
background: #303030; 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-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); background: -webkit-linear-gradient(left, #bcbcbc, #a7b4b7, #beb5a5, #adbec2, #b9c7cb);
@ -257,11 +257,6 @@ html {
background: #fff; background: #fff;
} }
.mediaInfoTimerIcon,
.starIcon {
color: #cb272a;
}
.emby-input, .emby-input,
.emby-textarea { .emby-textarea {
color: inherit; color: inherit;

View File

@ -223,7 +223,7 @@ html {
color: #fff !important; color: #fff !important;
} }
.detailSticky { .detailRibbon {
background: #303030; 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-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); background: -webkit-linear-gradient(left, #291a31, #033664, #011432, #141a3a, #291a31);
@ -261,11 +261,6 @@ html {
background: rgba(170, 170, 190, 0.2); background: rgba(170, 170, 190, 0.2);
} }
.mediaInfoTimerIcon,
.starIcon {
color: #cb272a;
}
.emby-input, .emby-input,
.emby-textarea { .emby-textarea {
color: inherit; color: inherit;

View File

@ -203,11 +203,11 @@ html {
background: rgba(30, 30, 30, 0.9); background: rgba(30, 30, 30, 0.9);
} }
.detailSticky { .detailRibbon {
background: rgba(32, 32, 32, 0.8); background: rgba(32, 32, 32, 0.8);
} }
.noBackdrop .detailSticky { .noBackdrop .detailRibbon {
background: #202020; background: #202020;
} }
@ -236,11 +236,6 @@ html {
background: rgba(170, 170, 190, 0.2); background: rgba(170, 170, 190, 0.2);
} }
.mediaInfoTimerIcon,
.starIcon {
color: #cb272a;
}
.emby-input, .emby-input,
.emby-textarea { .emby-textarea {
color: inherit; color: inherit;
@ -453,3 +448,8 @@ html {
.metadataSidebarIcon { .metadataSidebarIcon {
color: #00a4dc; color: #00a4dc;
} }
.emby-button.detailFloatingButton {
background-color: #00a4dc;
color: #fff;
}

View File

@ -221,7 +221,7 @@ html {
color: #fff !important; color: #fff !important;
} }
.detailSticky { .detailRibbon {
background-color: #303030; background-color: #303030;
color: #ccc; color: #ccc;
color: rgba(255, 255, 255, 0.87); color: rgba(255, 255, 255, 0.87);
@ -250,11 +250,6 @@ html {
background: #fff; background: #fff;
} }
.mediaInfoTimerIcon,
.starIcon {
color: #cb272a;
}
.emby-input, .emby-input,
.emby-textarea { .emby-textarea {
color: inherit; color: inherit;

View File

@ -307,7 +307,7 @@ a[data-role=button] {
color: #f8f8fe !important; color: #f8f8fe !important;
} }
.detailSticky { .detailRibbon {
background: #000420; background: #000420;
background: -moz-linear-gradient(left, #000420 0%, #06256f 18%, #2b052b 38%, #2b052b 68%, #06256f 81%, #000420 100%); 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%); background: -webkit-linear-gradient(left, #000420 0%, #06256f 18%, #2b052b 38%, #2b052b 68%, #06256f 81%, #000420 100%);
@ -344,11 +344,6 @@ a[data-role=button] {
background: rgba(170, 170, 190, 0.2); background: rgba(170, 170, 190, 0.2);
} }
.mediaInfoTimerIcon,
.starIcon {
color: #f2b01e;
}
.emby-input, .emby-input,
.emby-textarea { .emby-textarea {
color: inherit; color: inherit;

View File

@ -209,7 +209,7 @@ html {
color: #fff !important; color: #fff !important;
} }
.detailSticky { .detailRibbon {
background-color: #081b3b; background-color: #081b3b;
} }
@ -243,11 +243,6 @@ html {
background: rgba(170, 170, 190, 0.2); background: rgba(170, 170, 190, 0.2);
} }
.mediaInfoTimerIcon,
.starIcon {
color: #cb272a;
}
.emby-input, .emby-input,
.emby-textarea { .emby-textarea {
color: inherit; color: inherit;