diff --git a/src/assets/css/librarybrowser.css b/src/assets/css/librarybrowser.css index c6947b5961..354f96bb4f 100644 --- a/src/assets/css/librarybrowser.css +++ b/src/assets/css/librarybrowser.css @@ -507,7 +507,23 @@ .parentName { 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 { @@ -530,6 +546,35 @@ 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 { display: flex; flex-direction: column; @@ -557,10 +602,18 @@ } .layout-mobile .mainDetailButtons { - margin-top: 2em; + margin-top: 1em; margin-bottom: 0.5em; } +.subTitle { + margin: 0.15em 0 0.2em; +} + +.layout-mobile .subTitle { + margin: 0.2em 0 0.2em; +} + .detailPagePrimaryContainer { display: flex; align-items: center; @@ -571,7 +624,7 @@ .layout-mobile .detailPagePrimaryContainer { display: block; position: relative; - padding: 2.5em 3.3% 1em; + padding: 0.5em 3.3% 0.5em; } .layout-tv #itemDetailPage:not(.noBackdrop) .detailPagePrimaryContainer, @@ -613,6 +666,10 @@ margin: 1.25em 0; } +.layout-mobile .detailPageSecondaryContainer { + margin: 1em 0; +} + .detailImageContainer .card { position: absolute; top: 50%; @@ -722,7 +779,7 @@ div.itemDetailGalleryLink.defaultCardBackground { @media all and (max-width: 62.5em) { .parentName { - margin-bottom: 1em; + margin-bottom: 0; } .itemDetailPage { @@ -983,6 +1040,10 @@ div.itemDetailGalleryLink.defaultCardBackground { margin-bottom: 2.7em; } +.layout-mobile .verticalSection-extrabottompadding { + margin-bottom: 1em; +} + .sectionTitleButton, .sectionTitleIconButton { margin-right: 0 !important; @@ -1008,7 +1069,12 @@ div.itemDetailGalleryLink.defaultCardBackground { div:not(.sectionTitleContainer-cards) > .sectionTitle-cards { margin: 0; - padding-top: 1.25em; + padding-top: 0.5em; +} + +.layout-mobile :not(.sectionTitleContainer-cards) > .sectionTitle-cards { + margin: 0; + padding-top: 0.5em; } .sectionTitleButton { diff --git a/src/components/actionSheet/actionSheet.js b/src/components/actionSheet/actionSheet.js index c56f42a9d9..2e22111945 100644 --- a/src/components/actionSheet/actionSheet.js +++ b/src/components/actionSheet/actionSheet.js @@ -16,7 +16,7 @@ function getOffsets(elems) { return results; } - for (let elem of elems) { + for (const elem of elems) { let box = elem.getBoundingClientRect(); results.push({ @@ -135,7 +135,7 @@ export function show(options) { let renderIcon = false; let icons = []; let itemIcon; - for (let item of options.items) { + for (const item of options.items) { itemIcon = item.icon || (item.selected ? 'check' : null); diff --git a/src/components/groupedcards.js b/src/components/groupedcards.js index 602c4310f4..5f23d8bb18 100644 --- a/src/components/groupedcards.js +++ b/src/components/groupedcards.js @@ -22,7 +22,7 @@ define(['dom', 'appRouter', 'connectionManager'], function (dom, appRouter, conn return void appRouter.showItem(items[0]); } - var url = 'itemdetails.html?id=' + itemId + '&serverId=' + serverId; + var url = 'details?id=' + itemId + '&serverId=' + serverId; Dashboard.navigate(url); }); e.stopPropagation(); diff --git a/src/components/itemHelper.js b/src/components/itemHelper.js index b18f37110c..3508866bdb 100644 --- a/src/components/itemHelper.js +++ b/src/components/itemHelper.js @@ -1,14 +1,12 @@ define(['apphost', 'globalize'], function (appHost, globalize) { 'use strict'; - function getDisplayName(item, options) { + function getDisplayName(item, options = {}) { if (!item) { throw new Error('null item passed into getDisplayName'); } - options = options || {}; - if (item.Type === 'Timer') { item = item.ProgramInfo || item; } diff --git a/src/components/remotecontrol/remotecontrol.js b/src/components/remotecontrol/remotecontrol.js index 089915a834..9848b7e9cd 100644 --- a/src/components/remotecontrol/remotecontrol.js +++ b/src/components/remotecontrol/remotecontrol.js @@ -122,10 +122,10 @@ define(['browser', 'datetime', 'backdrop', 'libraryBrowser', 'listView', 'imageL var artistName; if (item.ArtistItems != null) { artistName = item.ArtistItems[0].Name; - context.querySelector('.nowPlayingAlbum').innerHTML = '${albumName}`; - context.querySelector('.nowPlayingArtist').innerHTML = '${artistName}`; - context.querySelector('.contextMenuAlbum').innerHTML = ' ` + globalize.translate('ViewAlbum') + ''; - context.querySelector('.contextMenuArtist').innerHTML = ' ` + globalize.translate('ViewArtist') + ''; + context.querySelector('.nowPlayingAlbum').innerHTML = '${albumName}`; + context.querySelector('.nowPlayingArtist').innerHTML = '${artistName}`; + context.querySelector('.contextMenuAlbum').innerHTML = ' ` + globalize.translate('ViewAlbum') + ''; + context.querySelector('.contextMenuArtist').innerHTML = ' ` + globalize.translate('ViewArtist') + ''; } else { artistName = item.Artists; context.querySelector('.nowPlayingAlbum').innerHTML = albumName; @@ -136,12 +136,12 @@ define(['browser', 'datetime', 'backdrop', 'libraryBrowser', 'listView', 'imageL } else if (item.Type == 'Episode') { if (item.SeasonName != null) { var seasonName = item.SeasonName; - context.querySelector('.nowPlayingSeason').innerHTML = '${seasonName}`; + context.querySelector('.nowPlayingSeason').innerHTML = '${seasonName}`; } if (item.SeriesName != null) { var seriesName = item.SeriesName; if (item.SeriesId != null) { - context.querySelector('.nowPlayingSerie').innerHTML = '${seriesName}`; + context.querySelector('.nowPlayingSerie').innerHTML = '${seriesName}`; } else { context.querySelector('.nowPlayingSerie').innerHTML = seriesName; } diff --git a/src/itemdetails.html b/src/controllers/itemDetails/itemDetails.html similarity index 90% rename from src/itemdetails.html rename to src/controllers/itemDetails/itemDetails.html index d6c8d64214..777439258a 100644 --- a/src/itemdetails.html +++ b/src/controllers/itemDetails/itemDetails.html @@ -1,8 +1,5 @@
-
@@ -15,87 +12,75 @@
- -
@@ -166,7 +151,7 @@
-
+

${HeaderNextUp}

@@ -178,7 +163,7 @@
-

+

diff --git a/src/controllers/itemDetails.js b/src/controllers/itemDetails/itemDetails.js similarity index 95% rename from src/controllers/itemDetails.js rename to src/controllers/itemDetails/itemDetails.js index 989edd26ca..cec61fb85f 100644 --- a/src/controllers/itemDetails.js +++ b/src/controllers/itemDetails/itemDetails.js @@ -28,15 +28,11 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function hideAll(page, className, show) { - var i; - var length; - var elems = page.querySelectorAll('.' + className); - - for (i = 0, length = elems.length; i < length; i++) { + for (const elem of page.querySelectorAll('.' + className)) { if (show) { - elems[i].classList.remove('hide'); + elem.classList.remove('hide'); } else { - elems[i].classList.add('hide'); + elem.classList.add('hide'); } } } @@ -75,7 +71,9 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti moreButton: false, recordButton: false }); - return html += '
'; + html += '
'; + + return html; } function renderSeriesTimerSchedule(page, apiClient, seriesTimerId) { @@ -143,9 +141,13 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti var mediaSources = item.MediaSources; instance._currentPlaybackMediaSources = mediaSources; + page.querySelector('.trackSelections').classList.remove('hide'); + select.setLabel(globalize.translate('LabelVersion')); + var currentValue = select.value; + var selectedId = mediaSources[0].Id; select.innerHTML = mediaSources.map(function (v) { var selected = v.Id === selectedId ? ' selected' : ''; @@ -242,12 +244,24 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti select.setLabel(globalize.translate('LabelSubtitles')); 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' : ''; select.innerHTML = '' + tracks.map(function (v) { selected = v.Index === selectedId ? ' selected' : ''; return ''; }).join(''); + + if (tracks.length > 1) { + select.removeAttribute('disabled'); + } else { + select.setAttribute('disabled', 'disabled'); + } + page.querySelector('.selectSubtitlesContainer').classList.remove('hide'); } else { select.innerHTML = ''; @@ -278,7 +292,12 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti var enableShuffle = item.IsFolder || -1 !== ['MusicAlbum', 'MusicGenre', 'MusicArtist'].indexOf(item.Type); hideAll(page, 'btnShuffle', enableShuffle); canPlay = true; - hideAll(page, 'btnResume', item.UserData && item.UserData.PlaybackPositionTicks > 0); + if (item.UserData && item.UserData.PlaybackPositionTicks > 0) { + hideAll(page, 'btnResume', true); + for (const elem of page.querySelectorAll('.btnPlay')) { + elem.querySelector('.detailButton-icon').classList.replace('play_arrow', 'replay'); + } + } } else { hideAll(page, 'btnPlay'); hideAll(page, 'btnResume'); @@ -324,8 +343,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti function getArtistLinksHtml(artists, serverId, context) { var html = []; - for (var i = 0, length = artists.length; i < length; i++) { - var artist = artists[i]; + for (const artist of artists) { var href = appRouter.getRouteUrl(artist, { context: context, itemType: 'MusicArtist', @@ -333,8 +351,9 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti }); html.push('' + artist.Name + ''); } + html = html.join(' / '); - return html = html.join(' / '); + return html; } /** @@ -371,6 +390,8 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti if (item.SeriesName && 'Season' === item.Type) { parentRoute = appRouter.getRouteUrl({ + Id: item.SeriesId, + Name: item.SeriesName, Type: 'Series', IsFolder: true, ServerId: item.ServerId @@ -414,36 +435,33 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti if (parentNameLast) { // Music if (layoutManager.mobile) { - html = '

' + parentNameHtml.join('
') + '

'; + html = '

' + parentNameHtml.join('
') + '

'; } else { - html = '

' + parentNameHtml.join(' - ') + '

'; + html = '

' + parentNameHtml.join(' - ') + '

'; } } else { - if (layoutManager.mobile) { - html = '

' + parentNameHtml.join('
') + '

'; - } else { - html = '

' + tvShowHtml + '

'; - } + html = '

' + tvShowHtml + '

'; } } var name = itemHelper.getDisplayName(item, { includeParentInfo: false }); - var offset = parentNameLast ? '.25em' : '.5em'; if (html && !parentNameLast) { - if (!layoutManager.mobile && tvSeasonHtml) { - html += '

' + tvSeasonHtml + ' - ' + name + '

'; + if (tvSeasonHtml) { + html += '

' + tvSeasonHtml + ' - ' + name + '

'; } else { - html += '

' + name + '

'; + html += '

' + name + '

'; } + } else if (item.OriginalTitle && item.OriginalTitle != item.Name) { + html = '

' + name + '

' + html; } else { - html = '

' + name + '

' + html; + html = '

' + name + '

' + html; } if (item.OriginalTitle && item.OriginalTitle != item.Name) { - html += '

' + item.OriginalTitle + '

'; + html += '

' + item.OriginalTitle + '

'; } container.innerHTML = html; @@ -511,7 +529,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti Emby.Page.setTitle(''); // Start rendering the artwork first - renderImage(page, item, apiClient, user); + renderImage(page, item); renderLogo(page, item, apiClient); renderBackdrop(item); renderDetailPageBackdrop(page, item, apiClient); @@ -672,7 +690,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } if (item.ExternalUrls) { - for (let url of item.ExternalUrls) { + for (const url of item.ExternalUrls) { links.push(`${url.Name}`); } } @@ -691,7 +709,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } } - function renderDetailImage(page, elem, item, apiClient, editable, imageLoader, indicators) { + function renderDetailImage(elem, item, imageLoader) { elem.classList.add('detailimg-hidemobile'); const itemArray = []; @@ -713,15 +731,11 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti imageLoader.lazyChildren(elem); } - function renderImage(page, item, apiClient, user) { + function renderImage(page, item) { renderDetailImage( - page, page.querySelector('.detailImageContainer'), item, - apiClient, - user.Policy.IsAdministrator && 'Photo' != item.MediaType, - imageLoader, - indicators + imageLoader ); } @@ -840,7 +854,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti function renderOverview(page, item) { var overviewElemnts = page.querySelectorAll('.overview'); - for (let overviewElemnt of overviewElemnts) { + for (const overviewElemnt of overviewElemnts) { var overview = item.Overview || ''; if (overview) { @@ -861,10 +875,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti expandButton.addEventListener('click', toggleLineClamp.bind(null, overviewElemnt)); - var anchors = overviewElemnt.querySelectorAll('a'); - - var anchors = overviewElemnt.querySelectorAll('a'); - for (let anchor of anchors) { + for (const anchor of overviewElemnt.querySelectorAll('a')) { anchor.setAttribute('target', '_blank'); } } else { @@ -874,19 +885,9 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } } - function renderGenres(page, item, context) { - context = context || inferContext(item); - var type; + function renderGenres(page, item, context = inferContext(item)) { var genres = item.GenreItems || []; - - switch (context) { - case 'music': - type = 'MusicGenre'; - break; - - default: - type = 'Genre'; - } + var type = context === 'music' ? 'MusicGenre' : 'Genre'; var html = genres.map(function (p) { return '