From 4fa5176982200c6588a63fcee87fc9f311fca4f0 Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Fri, 17 Oct 2025 16:42:40 -0400 Subject: [PATCH] Use float for item details poster (#7195) * Use float for item details poster * Add list view children to primary content * Move additional sections to primary container * Add series to list view children * Fix order of primary content sections --- src/controllers/itemDetails/index.html | 298 +++++++++++++------------ src/controllers/itemDetails/index.js | 56 +++-- src/index.html | 3 + src/styles/librarybrowser.scss | 70 +++--- src/themes/appletv/theme.scss | 1 + src/themes/blueradiance/theme.scss | 1 + src/themes/dark/theme.scss | 1 + src/themes/light/theme.scss | 1 + src/themes/purplehaze/theme.scss | 1 + src/themes/wmc/theme.scss | 1 + 10 files changed, 243 insertions(+), 190 deletions(-) diff --git a/src/controllers/itemDetails/index.html b/src/controllers/itemDetails/index.html index cd5439a10f..00373300d6 100644 --- a/src/controllers/itemDetails/index.html +++ b/src/controllers/itemDetails/index.html @@ -4,172 +4,186 @@
-
-
-
-
-
-
+
+
+ +
+
+
+
+
+
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
-
- +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
- +
- +
+

+

+

+ +

+

+

+

- - +
+
+
+
+
- +
+
+
+
- +
+
+
+
- - - +
- - + +
+

+ +

+
+
+
+
+
+
-
-
-
-
- -
-
- -
-
- -
-
- -
-
- -
- -
-

-

-

- -

-

-

-

- -
- -
-
- -
-
-
-
-
- -
-
-
-
- -
-
-
-
- -
-
-
-
-
-
-
- -
-

${Schedule}

-
-
- -
- -
-

${NextUp}

-
-
- -
-
-
-
-

- +

+

-
-
+
+
diff --git a/src/controllers/itemDetails/index.js b/src/controllers/itemDetails/index.js index fc0dc016d7..e425285050 100644 --- a/src/controllers/itemDetails/index.js +++ b/src/controllers/itemDetails/index.js @@ -45,6 +45,14 @@ import 'elements/emby-select/emby-select'; import 'styles/scrollstyles.scss'; +/** Item types that use a list view for their children. */ +const LIST_VIEW_TYPES = [ + BaseItemKind.MusicAlbum, + BaseItemKind.Playlist, + BaseItemKind.Season, + BaseItemKind.Series +]; + function autoFocus(container) { import('../../components/autoFocuser').then(({ default: autoFocuser }) => { autoFocuser.autoFocus(container); @@ -554,7 +562,6 @@ function reloadFromItem(instance, page, params, item, user) { renderBackdrop(page, item); // 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); @@ -749,12 +756,15 @@ function renderDetailImage(apiClient, elem, item, loader) { } function renderImage(page, item, apiClient) { - renderDetailImage( - apiClient, - page.querySelector('.detailImageContainer'), - item, - imageLoader - ); + page.querySelectorAll('.detailImageContainer') + .forEach(elem => { + renderDetailImage( + apiClient, + elem, + item, + imageLoader + ); + }); } function setPeopleHeader(page, item) { @@ -803,18 +813,22 @@ function setInitialCollapsibleState(page, item, apiClient, context, user) { page.querySelector('.collectionItems').innerHTML = ''; if (item.Type == 'Playlist') { - page.querySelector('#childrenCollapsible').classList.remove('hide'); + page.querySelector('#listChildrenCollapsible').classList.remove('hide'); + page.querySelector('#childrenCollapsible').classList.add('hide'); renderPlaylistItems(page, item); } else if (item.Type == 'Studio' || item.Type == 'Person' || item.Type == 'Genre' || item.Type == 'MusicGenre' || item.Type == 'MusicArtist') { - page.querySelector('#childrenCollapsible').classList.remove('hide'); + page.querySelector('#listChildrenCollapsible').classList.remove('hide'); + page.querySelector('#childrenCollapsible').classList.add('hide'); renderItemsByName(page, item); } else if (item.IsFolder) { if (item.Type == 'BoxSet') { + page.querySelector('#listChildrenCollapsible').classList.add('hide'); page.querySelector('#childrenCollapsible').classList.add('hide'); } renderChildren(page, item); } else { + page.querySelector('#listChildrenCollapsible').classList.add('hide'); page.querySelector('#childrenCollapsible').classList.add('hide'); } @@ -1338,6 +1352,9 @@ function renderTags(page, item) { } function renderChildren(page, item) { + const childrenCollapsible = page.querySelector(LIST_VIEW_TYPES.includes(item.Type) ? '#listChildrenCollapsible' : '#childrenCollapsible'); + const childrenItemsContainer = childrenCollapsible.querySelector('.itemsContainer'); + let fields = 'ItemCounts,PrimaryImageAspectRatio,CanDelete,MediaSourceCount'; const query = { ParentId: item.Id, @@ -1375,7 +1392,6 @@ function renderChildren(page, item) { let html = ''; let scrollX = false; let isList = false; - const childrenItemsContainer = page.querySelector('.childrenItemsContainer'); if (item.Type == 'MusicAlbum') { let showArtist = false; @@ -1451,7 +1467,7 @@ function renderChildren(page, item) { } if (item.Type !== 'BoxSet') { - page.querySelector('#childrenCollapsible').classList.remove('hide'); + childrenCollapsible.classList.remove('hide'); } if (scrollX) { childrenItemsContainer.classList.add('scrollX'); @@ -1502,21 +1518,23 @@ function renderChildren(page, item) { } }); + let childrenTitle = globalize.translate('Items'); if (item.Type == 'Season') { - page.querySelector('#childrenTitle').innerHTML = globalize.translate('Episodes'); + childrenTitle = globalize.translate('Episodes'); } else if (item.Type == 'Series') { - page.querySelector('#childrenTitle').innerHTML = globalize.translate('HeaderSeasons'); + childrenTitle = globalize.translate('HeaderSeasons'); } else if (item.Type == 'MusicAlbum') { - page.querySelector('#childrenTitle').innerHTML = globalize.translate('HeaderTracks'); - } else { - page.querySelector('#childrenTitle').innerHTML = globalize.translate('Items'); + childrenTitle = globalize.translate('HeaderTracks'); } + childrenCollapsible.querySelectorAll('.sectionTitle > span').forEach(el => { + el.innerText = childrenTitle; + }); if (item.Type == 'MusicAlbum' || item.Type == 'Season') { - page.querySelector('.childrenSectionHeader').classList.add('hide'); - page.querySelector('#childrenCollapsible').classList.add('verticalSection-extrabottompadding'); + childrenCollapsible.querySelector('.sectionTitle').classList.add('hide'); + childrenCollapsible.classList.add('verticalSection-extrabottompadding'); } else { - page.querySelector('.childrenSectionHeader').classList.remove('hide'); + childrenCollapsible.querySelector('.sectionTitle').classList.remove('hide'); } } diff --git a/src/index.html b/src/index.html index fca71a44a3..5d5009bdce 100644 --- a/src/index.html +++ b/src/index.html @@ -58,6 +58,9 @@ } .hide, + .layout-desktop .hide-desktop, + .layout-mobile .hide-mobile, + .layout-tv .hide-tv, .mouseIdle .hide-mouse-idle, .mouseIdle-tv .hide-mouse-idle-tv { display: none !important; diff --git a/src/styles/librarybrowser.scss b/src/styles/librarybrowser.scss index a604f27625..1a82a2de76 100644 --- a/src/styles/librarybrowser.scss +++ b/src/styles/librarybrowser.scss @@ -777,7 +777,7 @@ padding-left: 0; // Reset padding for focused button since 'margin-left' is 0 } -.detailPagePrimaryContainer { +.detailRibbon { display: flex; align-items: center; align-content: center; @@ -791,6 +791,8 @@ .layout-desktop & { position: relative; + margin-top: -7.2em; + height: 7.2em; } .layout-tv & { @@ -808,16 +810,6 @@ } } -.layout-desktop .detailRibbon { - margin-top: -7.2em; - height: 7.2em; -} - -.layout-tv .detailRibbon { - margin-top: 0; - height: inherit; -} - .infoWrapper { min-width: 0; max-width: 100%; @@ -843,6 +835,10 @@ max-width: 100%; } +.detailPagePrimaryContainer { + position: relative; +} + .detailPageSecondaryContainer { padding-top: 1.25em; @@ -856,9 +852,8 @@ } .detailImageContainer .card { - // important is needed here to override :focus setting - // the position to relative in the tv layout - position: absolute !important; + position: relative; + float: left; top: 20%; max-width: 25vw; max-height: 80vh; @@ -868,15 +863,9 @@ margin: 0; } - &.backdropCard { - top: 35%; - } - - &.squareCard { - top: 40%; - } - .layout-mobile & { + position: absolute; + top: auto; left: 5%; bottom: 1rem; max-width: 30vw; @@ -887,16 +876,16 @@ bottom: 0; } - &, - &.backdropCard, - &.squareCard { - top: auto; + &.backdropCard { + top: 1.6em; } } .layout-desktop & { left: 3.3%; - top: -80%; + // ribbon height (7.2em) * 1.8 + top: -12.96em; + margin-bottom: -12.96em; // match top offset width: 25vw; // FIXME: the fixed width + max height cause the card to be cropped this needs a proper fix max-height: none; @@ -904,9 +893,10 @@ .layout-tv & { left: 5%; - top: 50%; + top: 0; width: 25vw; - transform: translateY(-50%); + // match the width + margin-right: -25vw; } [dir="rtl"] & { @@ -925,6 +915,28 @@ .detailPagePrimaryContent { position: relative; + padding-top: 1.25em; + + [dir="ltr"] & { + padding-left: 32.45vw; + padding-right: 2%; + } + + [dir="rtl"] & { + padding-right: 32.45vw; + padding-left: 2%; + } + + .layout-mobile & { + padding-left: 5% !important; + padding-right: 5% !important; + } + + &::after { + content: ""; + display: table; + clear: both; + } } .layout-mobile, diff --git a/src/themes/appletv/theme.scss b/src/themes/appletv/theme.scss index 71cbabcd9b..aa97918851 100644 --- a/src/themes/appletv/theme.scss +++ b/src/themes/appletv/theme.scss @@ -252,6 +252,7 @@ a[data-role=button] { background: none; } +.noBackdropTransparency .detailPagePrimaryContainer, .noBackdropTransparency .detailPageSecondaryContainer { background-color: #d5e9f2; } diff --git a/src/themes/blueradiance/theme.scss b/src/themes/blueradiance/theme.scss index c6d0d7c68b..155f7314f7 100644 --- a/src/themes/blueradiance/theme.scss +++ b/src/themes/blueradiance/theme.scss @@ -243,6 +243,7 @@ a[data-role=button] { background: none; } +.noBackdropTransparency .detailPagePrimaryContainer, .noBackdropTransparency .detailPageSecondaryContainer { background: url(bg.jpg) center top no-repeat #033361; background-size: cover; diff --git a/src/themes/dark/theme.scss b/src/themes/dark/theme.scss index b646875929..64e75a6b20 100644 --- a/src/themes/dark/theme.scss +++ b/src/themes/dark/theme.scss @@ -225,6 +225,7 @@ html { background: none; } +.noBackdropTransparency .detailPagePrimaryContainer, .noBackdropTransparency .detailPageSecondaryContainer { background-color: #101010; } diff --git a/src/themes/light/theme.scss b/src/themes/light/theme.scss index f0235dc974..80f3c0adff 100644 --- a/src/themes/light/theme.scss +++ b/src/themes/light/theme.scss @@ -257,6 +257,7 @@ a[data-role=button] { color: inherit; } +.noBackdropTransparency .detailPagePrimaryContainer, .noBackdropTransparency .detailPageSecondaryContainer { background-color: #f2f2f2; } diff --git a/src/themes/purplehaze/theme.scss b/src/themes/purplehaze/theme.scss index 5e47b23537..6a3a20887f 100644 --- a/src/themes/purplehaze/theme.scss +++ b/src/themes/purplehaze/theme.scss @@ -326,6 +326,7 @@ a[data-role=button] { background: none; } +.noBackdropTransparency .detailPagePrimaryContainer, .noBackdropTransparency .detailPageSecondaryContainer { background: url(bg.jpg) center top no-repeat #030322; background-size: cover; diff --git a/src/themes/wmc/theme.scss b/src/themes/wmc/theme.scss index 2749ca1cff..98719d3efb 100644 --- a/src/themes/wmc/theme.scss +++ b/src/themes/wmc/theme.scss @@ -228,6 +228,7 @@ a[data-role=button] { background: none; } +.noBackdropTransparency .detailPagePrimaryContainer, .noBackdropTransparency .detailPageSecondaryContainer { background: linear-gradient(to bottom, #0f3562, #1162a4, #03215f); background-color: #0f3562;