diff --git a/package.json b/package.json
index 0154195c9e..8a9f0f6a08 100644
--- a/package.json
+++ b/package.json
@@ -52,7 +52,7 @@
"stylelint-order": "^4.1.0",
"webpack": "^4.44.1",
"webpack-merge": "^4.2.2",
- "webpack-stream": "^5.2.1",
+ "webpack-stream": "^6.0.0",
"worker-plugin": "^5.0.0"
},
"dependencies": {
@@ -60,7 +60,7 @@
"blurhash": "^1.1.3",
"classlist.js": "https://github.com/eligrey/classList.js/archive/1.2.20180112.tar.gz",
"core-js": "^3.6.5",
- "date-fns": "^2.15.0",
+ "date-fns": "^2.16.0",
"epubjs": "^0.3.85",
"fast-text-encoding": "^1.0.3",
"flv.js": "^1.5.0",
@@ -81,7 +81,7 @@
"resize-observer-polyfill": "^1.5.1",
"screenfull": "^5.0.2",
"sortablejs": "^1.10.2",
- "swiper": "^5.4.5",
+ "swiper": "^6.1.1",
"webcomponents.js": "^0.7.24",
"whatwg-fetch": "^3.4.0"
},
diff --git a/src/assets/css/videoosd.css b/src/assets/css/videoosd.css
index 59a485468d..808915e58b 100644
--- a/src/assets/css/videoosd.css
+++ b/src/assets/css/videoosd.css
@@ -248,8 +248,6 @@
}
@media all and (max-width: 30em) {
- .btnFastForward,
- .btnRewind,
.osdMediaInfo,
.osdPoster {
display: none !important;
diff --git a/src/bundle.js b/src/bundle.js
index 23a19169b5..25810f58ee 100644
--- a/src/bundle.js
+++ b/src/bundle.js
@@ -60,8 +60,8 @@ _define('resize-observer-polyfill', function() {
});
// swiper
-const swiper = require('swiper/js/swiper');
-require('swiper/css/swiper.min.css');
+const swiper = require('swiper/swiper-bundle');
+require('swiper/swiper-bundle.css');
_define('swiper', function() {
return swiper;
});
diff --git a/src/components/nowPlayingBar/nowPlayingBar.js b/src/components/nowPlayingBar/nowPlayingBar.js
index 7aa8c623b3..d2de2f60f2 100644
--- a/src/components/nowPlayingBar/nowPlayingBar.js
+++ b/src/components/nowPlayingBar/nowPlayingBar.js
@@ -701,7 +701,7 @@ import 'emby-ratingbutton';
const player = this;
currentRuntimeTicks = playbackManager.duration(player);
- updateTimeDisplay(playbackManager.currentTime(player), currentRuntimeTicks, playbackManager.getBufferedRanges(player));
+ updateTimeDisplay(playbackManager.currentTime(player) * 10000, currentRuntimeTicks, playbackManager.getBufferedRanges(player));
}
function releaseCurrentPlayer() {
diff --git a/src/components/playback/playbackmanager.js b/src/components/playback/playbackmanager.js
index 3b4099d540..cf21ef53a8 100644
--- a/src/components/playback/playbackmanager.js
+++ b/src/components/playback/playbackmanager.js
@@ -1618,11 +1618,7 @@ class PlaybackManager {
player = player || self._currentPlayer;
if (player && !enableLocalPlaylistManagement(player)) {
- if (player.isLocalPlayer) {
- return player.seek((ticks || 0) / 10000);
- } else {
- return player.seek(ticks);
- }
+ return player.seek(ticks);
}
changeStream(player, ticks);
@@ -1631,11 +1627,7 @@ class PlaybackManager {
self.seekRelative = function (offsetTicks, player) {
player = player || self._currentPlayer;
if (player && !enableLocalPlaylistManagement(player) && player.seekRelative) {
- if (player.isLocalPlayer) {
- return player.seekRelative((ticks || 0) / 10000);
- } else {
- return player.seekRelative(ticks);
- }
+ return player.seekRelative(ticks);
}
const ticks = getCurrentTicks(player) + offsetTicks;
@@ -3219,7 +3211,7 @@ class PlaybackManager {
return player.currentTime();
}
- return this.getCurrentTicks(player);
+ return this.getCurrentTicks(player) / 10000;
}
nextItem(player = this._currentPlayer) {
diff --git a/src/components/remotecontrol/remotecontrol.css b/src/components/remotecontrol/remotecontrol.css
index c260799585..1c31b4382b 100644
--- a/src/components/remotecontrol/remotecontrol.css
+++ b/src/components/remotecontrol/remotecontrol.css
@@ -222,18 +222,10 @@
margin: 0;
}
-.layout-mobile .nowPlayingSecondaryButtons .btnShuffleQueue {
- display: none;
-}
-
.layout-mobile .nowPlayingSecondaryButtons .volumecontrol {
display: none;
}
-.layout-mobile .nowPlayingSecondaryButtons .btnRepeat {
- display: none;
-}
-
.layout-desktop .nowPlayingInfoButtons .btnRepeat,
.layout-tv .nowPlayingInfoButtons .btnRepeat {
display: none;
@@ -362,7 +354,8 @@
border-radius: 0;
}
- .nowPlayingInfoButtons .btnRepeat {
+ .nowPlayingInfoButtons .btnRepeat,
+ .nowPlayingInfoButtons .btnRewind {
position: absolute;
left: 0;
margin-left: 0;
@@ -370,7 +363,8 @@
font-size: smaller;
}
- .nowPlayingInfoButtons .btnShuffleQueue {
+ .nowPlayingInfoButtons .btnShuffleQueue,
+ .nowPlayingInfoButtons .btnFastForward {
position: absolute;
right: 0;
margin-right: 0;
@@ -468,7 +462,6 @@
}
@media all and (max-width: 63em) {
- .nowPlayingSecondaryButtons .repeatToggleButton,
.nowPlayingInfoButtons .playlist .listItemMediaInfo,
.nowPlayingInfoButtons .btnStop {
display: none !important;
diff --git a/src/components/remotecontrol/remotecontrol.js b/src/components/remotecontrol/remotecontrol.js
index 3216241e7a..a0d158e396 100644
--- a/src/components/remotecontrol/remotecontrol.js
+++ b/src/components/remotecontrol/remotecontrol.js
@@ -134,7 +134,7 @@ function imageUrl(item, options) {
function updateNowPlayingInfo(context, state, serverId) {
const item = state.NowPlayingItem;
const displayName = item ? getNowPlayingNameHtml(item).replace('
', ' - ') : '';
- if (typeof item !== 'undefined') {
+ if (item) {
const nowPlayingServerId = (item.ServerId || serverId);
if (item.Type == 'Audio' || item.MediaStreams[0].Type == 'Audio') {
const songName = item.Name;
@@ -192,11 +192,11 @@ function updateNowPlayingInfo(context, state, serverId) {
context.querySelector('.nowPlayingPageTitle').classList.add('hide');
}
- const url = item ? seriesImageUrl(item, {
+ const url = seriesImageUrl(item, {
maxHeight: 300
}) || imageUrl(item, {
maxHeight: 300
- }) : null;
+ });
let contextButton = context.querySelector('.btnToggleContextMenu');
// We remove the previous event listener by replacing the item in each update event
@@ -228,18 +228,16 @@ function updateNowPlayingInfo(context, state, serverId) {
});
});
setImageUrl(context, state, url);
- if (item) {
- backdrop.setBackdrops([item]);
- apiClient.getItem(apiClient.getCurrentUserId(), item.Id).then(function (fullItem) {
- const userData = fullItem.UserData || {};
- const likes = userData.Likes == null ? '' : userData.Likes;
- context.querySelector('.nowPlayingPageUserDataButtonsTitle').innerHTML = '';
- context.querySelector('.nowPlayingPageUserDataButtons').innerHTML = '';
- });
- } else {
- backdrop.clearBackdrop();
- context.querySelector('.nowPlayingPageUserDataButtons').innerHTML = '';
- }
+ backdrop.setBackdrops([item]);
+ apiClient.getItem(apiClient.getCurrentUserId(), item.Id).then(function (fullItem) {
+ const userData = fullItem.UserData || {};
+ const likes = userData.Likes == null ? '' : userData.Likes;
+ context.querySelector('.nowPlayingPageUserDataButtonsTitle').innerHTML = '';
+ context.querySelector('.nowPlayingPageUserDataButtons').innerHTML = '';
+ });
+ } else {
+ backdrop.clearBackdrop();
+ context.querySelector('.nowPlayingPageUserDataButtons').innerHTML = '';
}
}
@@ -332,8 +330,14 @@ export default function () {
buttonVisible(context.querySelector('.btnNextTrack'), item != null);
buttonVisible(context.querySelector('.btnPreviousTrack'), item != null);
if (layoutManager.mobile) {
- buttonVisible(context.querySelector('.btnRewind'), false);
- buttonVisible(context.querySelector('.btnFastForward'), false);
+ const playingVideo = playbackManager.isPlayingVideo() && item !== null;
+ const playingAudio = !playbackManager.isPlayingVideo() && item !== null;
+ buttonVisible(context.querySelector('.btnRepeat'), playingAudio);
+ buttonVisible(context.querySelector('.btnShuffleQueue'), playingAudio);
+ buttonVisible(context.querySelector('.btnRewind'), playingVideo);
+ buttonVisible(context.querySelector('.btnFastForward'), playingVideo);
+ buttonVisible(context.querySelector('.nowPlayingSecondaryButtons .btnShuffleQueue'), playingVideo);
+ buttonVisible(context.querySelector('.nowPlayingSecondaryButtons .btnRepeat'), playingVideo);
} else {
buttonVisible(context.querySelector('.btnRewind'), item != null);
buttonVisible(context.querySelector('.btnFastForward'), item != null);
@@ -615,7 +619,7 @@ export default function () {
lastUpdateTime = now;
const player = this;
currentRuntimeTicks = playbackManager.duration(player);
- updateTimeDisplay(playbackManager.currentTime(player), currentRuntimeTicks);
+ updateTimeDisplay(playbackManager.currentTime(player) * 10000, currentRuntimeTicks);
}
}
diff --git a/src/components/serviceworker/notifications.js b/src/components/serviceworker/notifications.js
index 339d521bbc..9b50553244 100644
--- a/src/components/serviceworker/notifications.js
+++ b/src/components/serviceworker/notifications.js
@@ -26,7 +26,8 @@
});
}
- window.addEventListener('notificationclick', function (event) {
+ /* eslint-disable-next-line no-restricted-globals -- self is valid in a serviceworker environment */
+ self.addEventListener('notificationclick', function (event) {
var notification = event.notification;
notification.close();
diff --git a/src/components/slideshow/slideshow.js b/src/components/slideshow/slideshow.js
index 82f541a116..6e2d5c379c 100644
--- a/src/components/slideshow/slideshow.js
+++ b/src/components/slideshow/slideshow.js
@@ -256,7 +256,7 @@ export default function (options) {
/**
* Handles zoom changes.
*/
- function onZoomChange(scale, imageEl, slideEl) {
+ function onZoomChange(swiper, scale, imageEl, slideEl) {
const zoomImage = slideEl.querySelector('.swiper-zoom-fakeimg');
if (zoomImage) {
diff --git a/src/components/syncPlay/syncPlayManager.js b/src/components/syncPlay/syncPlayManager.js
index 2366172a79..26d6cdbad1 100644
--- a/src/components/syncPlay/syncPlayManager.js
+++ b/src/components/syncPlay/syncPlayManager.js
@@ -741,7 +741,7 @@ class SyncPlayManager {
const playAtTime = this.lastCommand.When;
- const currentPositionTicks = playbackManager.currentTime();
+ const currentPositionTicks = playbackManager.currentTime() * 10000;
// Estimate PositionTicks on server
const serverPositionTicks = this.lastCommand.PositionTicks + ((currentTime - playAtTime) + this.timeOffsetWithServer) * 10000;
// Measure delay that needs to be recovered
diff --git a/src/components/upnextdialog/upnextdialog.js b/src/components/upnextdialog/upnextdialog.js
index e28bb03abe..69cc6512fe 100644
--- a/src/components/upnextdialog/upnextdialog.js
+++ b/src/components/upnextdialog/upnextdialog.js
@@ -256,7 +256,7 @@ import 'flexStyles';
const runtimeTicks = playbackManager.duration(options.player);
if (runtimeTicks) {
- const timeRemainingTicks = runtimeTicks - playbackManager.currentTime(options.player);
+ const timeRemainingTicks = runtimeTicks - playbackManager.currentTime(options.player) * 10000;
return Math.round(timeRemainingTicks / 10000);
}
diff --git a/src/controllers/itemDetails/index.js b/src/controllers/itemDetails/index.js
index f837d3fc1d..b1781e75f0 100644
--- a/src/controllers/itemDetails/index.js
+++ b/src/controllers/itemDetails/index.js
@@ -29,2006 +29,2003 @@ import 'emby-ratingbutton';
import 'emby-scroller';
import 'emby-select';
-/* eslint-disable indent */
+function getPromise(apiClient, params) {
+ const id = params.id;
- function getPromise(apiClient, params) {
- const id = params.id;
-
- if (id) {
- return apiClient.getItem(apiClient.getCurrentUserId(), id);
- }
-
- if (params.seriesTimerId) {
- return apiClient.getLiveTvSeriesTimer(params.seriesTimerId);
- }
-
- if (params.genre) {
- return apiClient.getGenre(params.genre, apiClient.getCurrentUserId());
- }
-
- if (params.musicgenre) {
- return apiClient.getMusicGenre(params.musicgenre, apiClient.getCurrentUserId());
- }
-
- if (params.musicartist) {
- return apiClient.getArtist(params.musicartist, apiClient.getCurrentUserId());
- }
-
- throw new Error('Invalid request');
+ if (id) {
+ return apiClient.getItem(apiClient.getCurrentUserId(), id);
}
- function hideAll(page, className, show) {
- for (const elem of page.querySelectorAll('.' + className)) {
- if (show) {
- elem.classList.remove('hide');
- } else {
- elem.classList.add('hide');
- }
+ if (params.seriesTimerId) {
+ return apiClient.getLiveTvSeriesTimer(params.seriesTimerId);
+ }
+
+ if (params.genre) {
+ return apiClient.getGenre(params.genre, apiClient.getCurrentUserId());
+ }
+
+ if (params.musicgenre) {
+ return apiClient.getMusicGenre(params.musicgenre, apiClient.getCurrentUserId());
+ }
+
+ if (params.musicartist) {
+ return apiClient.getArtist(params.musicartist, apiClient.getCurrentUserId());
+ }
+
+ throw new Error('Invalid request');
+}
+
+function hideAll(page, className, show) {
+ for (const elem of page.querySelectorAll('.' + className)) {
+ if (show) {
+ elem.classList.remove('hide');
+ } else {
+ elem.classList.add('hide');
}
}
+}
- function getContextMenuOptions(item, user, button) {
- return {
- item: item,
- open: false,
- play: false,
- playAllFromHere: false,
- queueAllFromHere: false,
- positionTo: button,
- cancelTimer: false,
- record: false,
- deleteItem: item.CanDelete === true,
- shuffle: false,
- instantMix: false,
- user: user,
- share: true
- };
- }
+function getContextMenuOptions(item, user, button) {
+ return {
+ item: item,
+ open: false,
+ play: false,
+ playAllFromHere: false,
+ queueAllFromHere: false,
+ positionTo: button,
+ cancelTimer: false,
+ record: false,
+ deleteItem: item.CanDelete === true,
+ shuffle: false,
+ instantMix: false,
+ user: user,
+ share: true
+ };
+}
- function getProgramScheduleHtml(items) {
- let html = '';
+function getProgramScheduleHtml(items) {
+ let html = '';
- html += '
';
- html += listView.getListViewHtml({
- items: items,
- enableUserDataButtons: false,
- image: true,
- imageSource: 'channel',
- showProgramDateTime: true,
- showChannel: false,
- mediaInfo: false,
- action: 'none',
- moreButton: false,
- recordButton: false
- });
+ html += '
';
+ html += listView.getListViewHtml({
+ items: items,
+ enableUserDataButtons: false,
+ image: true,
+ imageSource: 'channel',
+ showProgramDateTime: true,
+ showChannel: false,
+ mediaInfo: false,
+ action: 'none',
+ moreButton: false,
+ recordButton: false
+ });
- html += '
';
+ html += '
';
- return html;
- }
+ return html;
+}
- function renderSeriesTimerSchedule(page, apiClient, seriesTimerId) {
- apiClient.getLiveTvTimers({
- UserId: apiClient.getCurrentUserId(),
- ImageTypeLimit: 1,
- EnableImageTypes: 'Primary,Backdrop,Thumb',
- SortBy: 'StartDate',
- EnableTotalRecordCount: false,
- EnableUserData: false,
- SeriesTimerId: seriesTimerId,
- Fields: 'ChannelInfo,ChannelImage'
- }).then(function (result) {
- if (result.Items.length && result.Items[0].SeriesTimerId != seriesTimerId) {
- result.Items = [];
- }
-
- const html = getProgramScheduleHtml(result.Items);
- const scheduleTab = page.querySelector('.seriesTimerSchedule');
- scheduleTab.innerHTML = html;
- imageLoader.lazyChildren(scheduleTab);
- });
- }
-
- function renderTimerEditor(page, item, apiClient, user) {
- if (item.Type !== 'Recording' || !user.Policy.EnableLiveTvManagement || !item.TimerId || item.Status !== 'InProgress') {
- return void hideAll(page, 'btnCancelTimer');
+function renderSeriesTimerSchedule(page, apiClient, seriesTimerId) {
+ apiClient.getLiveTvTimers({
+ UserId: apiClient.getCurrentUserId(),
+ ImageTypeLimit: 1,
+ EnableImageTypes: 'Primary,Backdrop,Thumb',
+ SortBy: 'StartDate',
+ EnableTotalRecordCount: false,
+ EnableUserData: false,
+ SeriesTimerId: seriesTimerId,
+ Fields: 'ChannelInfo,ChannelImage'
+ }).then(function (result) {
+ if (result.Items.length && result.Items[0].SeriesTimerId != seriesTimerId) {
+ result.Items = [];
}
- hideAll(page, 'btnCancelTimer', true);
+ const html = getProgramScheduleHtml(result.Items);
+ const scheduleTab = page.querySelector('.seriesTimerSchedule');
+ scheduleTab.innerHTML = html;
+ imageLoader.lazyChildren(scheduleTab);
+ });
+}
+
+function renderTimerEditor(page, item, apiClient, user) {
+ if (item.Type !== 'Recording' || !user.Policy.EnableLiveTvManagement || !item.TimerId || item.Status !== 'InProgress') {
+ return void hideAll(page, 'btnCancelTimer');
}
- function renderSeriesTimerEditor(page, item, apiClient, user) {
- if (item.Type !== 'SeriesTimer') {
- return void hideAll(page, 'btnCancelSeriesTimer');
- }
+ hideAll(page, 'btnCancelTimer', true);
+}
- if (user.Policy.EnableLiveTvManagement) {
- import('seriesRecordingEditor').then(({default: seriesRecordingEditor}) => {
- seriesRecordingEditor.embed(item, apiClient.serverId(), {
- context: page.querySelector('.seriesRecordingEditor')
- });
- });
-
- page.querySelector('.seriesTimerScheduleSection').classList.remove('hide');
- hideAll(page, 'btnCancelSeriesTimer', true);
- return void renderSeriesTimerSchedule(page, apiClient, item.Id);
- }
-
- page.querySelector('.seriesTimerScheduleSection').classList.add('hide');
+function renderSeriesTimerEditor(page, item, apiClient, user) {
+ if (item.Type !== 'SeriesTimer') {
return void hideAll(page, 'btnCancelSeriesTimer');
}
- function renderTrackSelections(page, instance, item, forceReload) {
- const select = page.querySelector('.selectSource');
-
- if (!item.MediaSources || !itemHelper.supportsMediaSourceSelection(item) || playbackManager.getSupportedCommands().indexOf('PlayMediaSource') === -1 || !playbackManager.canPlay(item)) {
- page.querySelector('.trackSelections').classList.add('hide');
- select.innerHTML = '';
- page.querySelector('.selectVideo').innerHTML = '';
- page.querySelector('.selectAudio').innerHTML = '';
- page.querySelector('.selectSubtitles').innerHTML = '';
- return;
- }
-
- const mediaSources = item.MediaSources;
- instance._currentPlaybackMediaSources = mediaSources;
-
- page.querySelector('.trackSelections').classList.remove('hide');
- select.setLabel(globalize.translate('LabelVersion'));
-
- const currentValue = select.value;
-
- const selectedId = mediaSources[0].Id;
- select.innerHTML = mediaSources.map(function (v) {
- const selected = v.Id === selectedId ? ' selected' : '';
- return '';
- }).join('');
-
- if (mediaSources.length > 1) {
- page.querySelector('.selectSourceContainer').classList.remove('hide');
- } else {
- page.querySelector('.selectSourceContainer').classList.add('hide');
- }
-
- if (select.value !== currentValue || forceReload) {
- renderVideoSelections(page, mediaSources);
- renderAudioSelections(page, mediaSources);
- renderSubtitleSelections(page, mediaSources);
- }
- }
-
- function renderVideoSelections(page, mediaSources) {
- const mediaSourceId = page.querySelector('.selectSource').value;
- const mediaSource = mediaSources.filter(function (m) {
- return m.Id === mediaSourceId;
- })[0];
-
- const tracks = mediaSource.MediaStreams.filter(function (m) {
- return m.Type === 'Video';
+ if (user.Policy.EnableLiveTvManagement) {
+ import('seriesRecordingEditor').then(({ default: seriesRecordingEditor }) => {
+ seriesRecordingEditor.embed(item, apiClient.serverId(), {
+ context: page.querySelector('.seriesRecordingEditor')
+ });
});
- const select = page.querySelector('.selectVideo');
- select.setLabel(globalize.translate('LabelVideo'));
- const selectedId = tracks.length ? tracks[0].Index : -1;
- select.innerHTML = tracks.map(function (v) {
- const selected = v.Index === selectedId ? ' selected' : '';
- const titleParts = [];
- const resolutionText = mediaInfo.getResolutionText(v);
+ page.querySelector('.seriesTimerScheduleSection').classList.remove('hide');
+ hideAll(page, 'btnCancelSeriesTimer', true);
+ return void renderSeriesTimerSchedule(page, apiClient, item.Id);
+ }
- if (resolutionText) {
- titleParts.push(resolutionText);
- }
+ page.querySelector('.seriesTimerScheduleSection').classList.add('hide');
+ return void hideAll(page, 'btnCancelSeriesTimer');
+}
- if (v.Codec) {
- titleParts.push(v.Codec.toUpperCase());
- }
+function renderTrackSelections(page, instance, item, forceReload) {
+ const select = page.querySelector('.selectSource');
- return '';
- }).join('');
+ if (!item.MediaSources || !itemHelper.supportsMediaSourceSelection(item) || playbackManager.getSupportedCommands().indexOf('PlayMediaSource') === -1 || !playbackManager.canPlay(item)) {
+ page.querySelector('.trackSelections').classList.add('hide');
+ select.innerHTML = '';
+ page.querySelector('.selectVideo').innerHTML = '';
+ page.querySelector('.selectAudio').innerHTML = '';
+ page.querySelector('.selectSubtitles').innerHTML = '';
+ return;
+ }
+
+ const mediaSources = item.MediaSources;
+ instance._currentPlaybackMediaSources = mediaSources;
+
+ page.querySelector('.trackSelections').classList.remove('hide');
+ select.setLabel(globalize.translate('LabelVersion'));
+
+ const currentValue = select.value;
+
+ const selectedId = mediaSources[0].Id;
+ select.innerHTML = mediaSources.map(function (v) {
+ const selected = v.Id === selectedId ? ' selected' : '';
+ return '';
+ }).join('');
+
+ if (mediaSources.length > 1) {
+ page.querySelector('.selectSourceContainer').classList.remove('hide');
+ } else {
+ page.querySelector('.selectSourceContainer').classList.add('hide');
+ }
+
+ if (select.value !== currentValue || forceReload) {
+ renderVideoSelections(page, mediaSources);
+ renderAudioSelections(page, mediaSources);
+ renderSubtitleSelections(page, mediaSources);
+ }
+}
+
+function renderVideoSelections(page, mediaSources) {
+ const mediaSourceId = page.querySelector('.selectSource').value;
+ const mediaSource = mediaSources.filter(function (m) {
+ return m.Id === mediaSourceId;
+ })[0];
+
+ const tracks = mediaSource.MediaStreams.filter(function (m) {
+ return m.Type === 'Video';
+ });
+
+ const select = page.querySelector('.selectVideo');
+ select.setLabel(globalize.translate('LabelVideo'));
+ const selectedId = tracks.length ? tracks[0].Index : -1;
+ select.innerHTML = tracks.map(function (v) {
+ const selected = v.Index === selectedId ? ' selected' : '';
+ const titleParts = [];
+ const resolutionText = mediaInfo.getResolutionText(v);
+
+ if (resolutionText) {
+ titleParts.push(resolutionText);
+ }
+
+ if (v.Codec) {
+ titleParts.push(v.Codec.toUpperCase());
+ }
+
+ return '';
+ }).join('');
+ select.setAttribute('disabled', 'disabled');
+
+ if (tracks.length) {
+ page.querySelector('.selectVideoContainer').classList.remove('hide');
+ } else {
+ page.querySelector('.selectVideoContainer').classList.add('hide');
+ }
+}
+
+function renderAudioSelections(page, mediaSources) {
+ const mediaSourceId = page.querySelector('.selectSource').value;
+ const mediaSource = mediaSources.filter(function (m) {
+ return m.Id === mediaSourceId;
+ })[0];
+ const tracks = mediaSource.MediaStreams.filter(function (m) {
+ return m.Type === 'Audio';
+ });
+ const select = page.querySelector('.selectAudio');
+ select.setLabel(globalize.translate('Audio'));
+ const selectedId = mediaSource.DefaultAudioStreamIndex;
+ select.innerHTML = tracks.map(function (v) {
+ const selected = v.Index === selectedId ? ' selected' : '';
+ return '';
+ }).join('');
+
+ if (tracks.length > 1) {
+ select.removeAttribute('disabled');
+ } else {
select.setAttribute('disabled', 'disabled');
-
- if (tracks.length) {
- page.querySelector('.selectVideoContainer').classList.remove('hide');
- } else {
- page.querySelector('.selectVideoContainer').classList.add('hide');
- }
}
- function renderAudioSelections(page, mediaSources) {
- const mediaSourceId = page.querySelector('.selectSource').value;
- const mediaSource = mediaSources.filter(function (m) {
- return m.Id === mediaSourceId;
- })[0];
- const tracks = mediaSource.MediaStreams.filter(function (m) {
- return m.Type === 'Audio';
- });
- const select = page.querySelector('.selectAudio');
- select.setLabel(globalize.translate('Audio'));
- const selectedId = mediaSource.DefaultAudioStreamIndex;
- select.innerHTML = tracks.map(function (v) {
- const selected = v.Index === selectedId ? ' selected' : '';
+ if (tracks.length) {
+ page.querySelector('.selectAudioContainer').classList.remove('hide');
+ } else {
+ page.querySelector('.selectAudioContainer').classList.add('hide');
+ }
+}
+
+function renderSubtitleSelections(page, mediaSources) {
+ const mediaSourceId = page.querySelector('.selectSource').value;
+ const mediaSource = mediaSources.filter(function (m) {
+ return m.Id === mediaSourceId;
+ })[0];
+ const tracks = mediaSource.MediaStreams.filter(function (m) {
+ return m.Type === 'Subtitle';
+ });
+ const select = page.querySelector('.selectSubtitles');
+ select.setLabel(globalize.translate('Subtitles'));
+ const selectedId = mediaSource.DefaultSubtitleStreamIndex == null ? -1 : mediaSource.DefaultSubtitleStreamIndex;
+
+ const videoTracks = mediaSource.MediaStreams.filter(function (m) {
+ return m.Type === 'Video';
+ });
+
+ // This only makes sense on Video items
+ if (videoTracks.length) {
+ let selected = selectedId === -1 ? ' selected' : '';
+ select.innerHTML = '' + tracks.map(function (v) {
+ selected = v.Index === selectedId ? ' selected' : '';
return '';
}).join('');
- if (tracks.length > 1) {
+ if (tracks.length > 0) {
select.removeAttribute('disabled');
} else {
select.setAttribute('disabled', 'disabled');
}
- if (tracks.length) {
- page.querySelector('.selectAudioContainer').classList.remove('hide');
- } else {
- page.querySelector('.selectAudioContainer').classList.add('hide');
- }
+ page.querySelector('.selectSubtitlesContainer').classList.remove('hide');
+ } else {
+ select.innerHTML = '';
+ page.querySelector('.selectSubtitlesContainer').classList.add('hide');
}
+}
- function renderSubtitleSelections(page, mediaSources) {
- const mediaSourceId = page.querySelector('.selectSource').value;
- const mediaSource = mediaSources.filter(function (m) {
- return m.Id === mediaSourceId;
- })[0];
- const tracks = mediaSource.MediaStreams.filter(function (m) {
- return m.Type === 'Subtitle';
- });
- const select = page.querySelector('.selectSubtitles');
- select.setLabel(globalize.translate('Subtitles'));
- const selectedId = mediaSource.DefaultSubtitleStreamIndex == null ? -1 : mediaSource.DefaultSubtitleStreamIndex;
+function reloadPlayButtons(page, item) {
+ let canPlay = false;
- const videoTracks = mediaSource.MediaStreams.filter(function (m) {
- return m.Type === 'Video';
- });
+ if (item.Type == 'Program') {
+ const now = new Date();
- // This only makes sense on Video items
- if (videoTracks.length) {
- let selected = selectedId === -1 ? ' selected' : '';
- select.innerHTML = '' + tracks.map(function (v) {
- selected = v.Index === selectedId ? ' selected' : '';
- return '';
- }).join('');
-
- if (tracks.length > 0) {
- select.removeAttribute('disabled');
- } else {
- select.setAttribute('disabled', 'disabled');
- }
-
- page.querySelector('.selectSubtitlesContainer').classList.remove('hide');
- } else {
- select.innerHTML = '';
- page.querySelector('.selectSubtitlesContainer').classList.add('hide');
- }
- }
-
- function reloadPlayButtons(page, item) {
- let canPlay = false;
-
- if (item.Type == 'Program') {
- const now = new Date();
-
- if (now >= datetime.parseISO8601Date(item.StartDate, true) && now < datetime.parseISO8601Date(item.EndDate, true)) {
- hideAll(page, 'btnPlay', true);
- canPlay = true;
- } else {
- hideAll(page, 'btnPlay');
- }
-
- hideAll(page, 'btnResume');
- hideAll(page, 'btnInstantMix');
- hideAll(page, 'btnShuffle');
- } else if (playbackManager.canPlay(item)) {
+ if (now >= datetime.parseISO8601Date(item.StartDate, true) && now < datetime.parseISO8601Date(item.EndDate, true)) {
hideAll(page, 'btnPlay', true);
- const enableInstantMix = ['Audio', 'MusicAlbum', 'MusicGenre', 'MusicArtist'].indexOf(item.Type) !== -1;
- hideAll(page, 'btnInstantMix', enableInstantMix);
- const enableShuffle = item.IsFolder || ['MusicAlbum', 'MusicGenre', 'MusicArtist'].indexOf(item.Type) !== -1;
- hideAll(page, 'btnShuffle', enableShuffle);
canPlay = true;
-
- 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 {
hideAll(page, 'btnPlay');
- hideAll(page, 'btnResume');
- hideAll(page, 'btnInstantMix');
- hideAll(page, 'btnShuffle');
}
- return canPlay;
+ hideAll(page, 'btnResume');
+ hideAll(page, 'btnInstantMix');
+ hideAll(page, 'btnShuffle');
+ } else if (playbackManager.canPlay(item)) {
+ hideAll(page, 'btnPlay', true);
+ const enableInstantMix = ['Audio', 'MusicAlbum', 'MusicGenre', 'MusicArtist'].indexOf(item.Type) !== -1;
+ hideAll(page, 'btnInstantMix', enableInstantMix);
+ const enableShuffle = item.IsFolder || ['MusicAlbum', 'MusicGenre', 'MusicArtist'].indexOf(item.Type) !== -1;
+ hideAll(page, 'btnShuffle', enableShuffle);
+ canPlay = true;
+
+ 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 {
+ hideAll(page, 'btnPlay');
+ hideAll(page, 'btnResume');
+ hideAll(page, 'btnInstantMix');
+ hideAll(page, 'btnShuffle');
}
- function reloadUserDataButtons(page, item) {
- let i;
- let length;
- const btnPlaystates = page.querySelectorAll('.btnPlaystate');
+ return canPlay;
+}
- for (i = 0, length = btnPlaystates.length; i < length; i++) {
- const btnPlaystate = btnPlaystates[i];
+function reloadUserDataButtons(page, item) {
+ let i;
+ let length;
+ const btnPlaystates = page.querySelectorAll('.btnPlaystate');
- if (itemHelper.canMarkPlayed(item)) {
- btnPlaystate.classList.remove('hide');
- btnPlaystate.setItem(item);
- } else {
- btnPlaystate.classList.add('hide');
- btnPlaystate.setItem(null);
- }
- }
+ for (i = 0, length = btnPlaystates.length; i < length; i++) {
+ const btnPlaystate = btnPlaystates[i];
- const btnUserRatings = page.querySelectorAll('.btnUserRating');
-
- for (i = 0, length = btnUserRatings.length; i < length; i++) {
- const btnUserRating = btnUserRatings[i];
-
- if (itemHelper.canRate(item)) {
- btnUserRating.classList.remove('hide');
- btnUserRating.setItem(item);
- } else {
- btnUserRating.classList.add('hide');
- btnUserRating.setItem(null);
- }
+ if (itemHelper.canMarkPlayed(item)) {
+ btnPlaystate.classList.remove('hide');
+ btnPlaystate.setItem(item);
+ } else {
+ btnPlaystate.classList.add('hide');
+ btnPlaystate.setItem(null);
}
}
- function getArtistLinksHtml(artists, serverId, context) {
- const html = [];
+ const btnUserRatings = page.querySelectorAll('.btnUserRating');
- for (const artist of artists) {
- const href = appRouter.getRouteUrl(artist, {
- context: context,
- itemType: 'MusicArtist',
- serverId: serverId
- });
- html.push('' + artist.Name + '');
+ for (i = 0, length = btnUserRatings.length; i < length; i++) {
+ const btnUserRating = btnUserRatings[i];
+
+ if (itemHelper.canRate(item)) {
+ btnUserRating.classList.remove('hide');
+ btnUserRating.setItem(item);
+ } else {
+ btnUserRating.classList.add('hide');
+ btnUserRating.setItem(null);
}
-
- return html.join(' / ');
}
+}
- /**
- * 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) {
- let parentRoute;
- const parentNameHtml = [];
- let parentNameLast = false;
+function getArtistLinksHtml(artists, serverId, context) {
+ const html = [];
- if (item.AlbumArtists) {
- parentNameHtml.push(getArtistLinksHtml(item.AlbumArtists, item.ServerId, context));
- parentNameLast = true;
- } else if (item.ArtistItems && item.ArtistItems.length && item.Type === 'MusicVideo') {
- parentNameHtml.push(getArtistLinksHtml(item.ArtistItems, item.ServerId, context));
- parentNameLast = true;
- } else if (item.SeriesName && item.Type === 'Episode') {
- parentRoute = appRouter.getRouteUrl({
- Id: item.SeriesId,
- Name: item.SeriesName,
- Type: 'Series',
- IsFolder: true,
- ServerId: item.ServerId
- }, {
- context: context
- });
- parentNameHtml.push('' + item.SeriesName + '');
- } else if (item.IsSeries || item.EpisodeTitle) {
- parentNameHtml.push(item.Name);
- }
-
- if (item.SeriesName && item.Type === 'Season') {
- parentRoute = appRouter.getRouteUrl({
- Id: item.SeriesId,
- Name: item.SeriesName,
- Type: 'Series',
- IsFolder: true,
- ServerId: item.ServerId
- }, {
- context: context
- });
- parentNameHtml.push('' + item.SeriesName + '');
- } else if (item.ParentIndexNumber != null && item.Type === 'Episode') {
- parentRoute = appRouter.getRouteUrl({
- Id: item.SeasonId,
- Name: item.SeasonName,
- Type: 'Season',
- IsFolder: true,
- ServerId: item.ServerId
- }, {
- context: context
- });
- parentNameHtml.push('' + item.SeasonName + '');
- } else if (item.ParentIndexNumber != null && item.IsSeries) {
- parentNameHtml.push(item.SeasonName || 'S' + item.ParentIndexNumber);
- } else if (item.Album && item.AlbumId && (item.Type === 'MusicVideo' || item.Type === 'Audio')) {
- parentRoute = appRouter.getRouteUrl({
- Id: item.AlbumId,
- Name: item.Album,
- Type: 'MusicAlbum',
- IsFolder: true,
- ServerId: item.ServerId
- }, {
- context: context
- });
- parentNameHtml.push('' + item.Album + '');
- } else if (item.Album) {
- parentNameHtml.push(item.Album);
- }
-
- // FIXME: This whole section needs some refactoring, so it becames easier to scale across all form factors. See GH #1022
- let html = '';
- const tvShowHtml = parentNameHtml[0];
- const tvSeasonHtml = parentNameHtml[1];
-
- if (parentNameHtml.length) {
- if (parentNameLast) {
- // Music
- if (layoutManager.mobile) {
- html = '' + parentNameHtml.join('') + '
';
- } else {
- html = '' + parentNameHtml.join(' - ') + '
';
- }
- } else {
- html = '' + tvShowHtml + '
';
- }
- }
-
- const name = itemHelper.getDisplayName(item, {
- includeParentInfo: false
+ for (const artist of artists) {
+ const href = appRouter.getRouteUrl(artist, {
+ context: context,
+ itemType: 'MusicArtist',
+ serverId: serverId
});
-
- if (html && !parentNameLast) {
- if (tvSeasonHtml) {
- html += '' + tvSeasonHtml + ' - ' + name + '
';
- } else {
- html += '' + name + '
';
- }
- } else if (item.OriginalTitle && item.OriginalTitle != item.Name) {
- html = '' + name + '
' + html;
- } else {
- html = '' + name + '
' + html;
- }
-
- if (item.OriginalTitle && item.OriginalTitle != item.Name) {
- html += '' + item.OriginalTitle + '
';
- }
-
- container.innerHTML = html;
-
- if (html.length) {
- container.classList.remove('hide');
- } else {
- container.classList.add('hide');
- }
+ html.push('' + artist.Name + '');
}
- function setTrailerButtonVisibility(page, item) {
- if ((item.LocalTrailerCount || item.RemoteTrailers && item.RemoteTrailers.length) && playbackManager.getSupportedCommands().indexOf('PlayTrailers') !== -1) {
- hideAll(page, 'btnPlayTrailer', true);
- } else {
- hideAll(page, 'btnPlayTrailer');
- }
- }
+ return html.join(' / ');
+}
- function renderBackdrop(item) {
- if (dom.getWindowSize().innerWidth >= 1000) {
- backdrop.setBackdrops([item]);
- } else {
- backdrop.clearBackdrop();
- }
- }
+/**
+ * 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) {
+ let parentRoute;
+ const parentNameHtml = [];
+ let parentNameLast = false;
- function renderDetailPageBackdrop(page, item, apiClient) {
- let imgUrl;
- let hasbackdrop = false;
- const itemBackdropElement = page.querySelector('#itemBackdrop');
-
- if (!layoutManager.mobile && !userSettings.detailsBanner()) {
- return false;
- }
-
- if (item.BackdropImageTags && item.BackdropImageTags.length) {
- imgUrl = apiClient.getScaledImageUrl(item.Id, {
- type: 'Backdrop',
- maxWidth: dom.getScreenWidth(),
- index: 0,
- tag: item.BackdropImageTags[0]
- });
- imageLoader.lazyImage(itemBackdropElement, imgUrl);
- hasbackdrop = true;
- } else if (item.ParentBackdropItemId && item.ParentBackdropImageTags && item.ParentBackdropImageTags.length) {
- imgUrl = apiClient.getScaledImageUrl(item.ParentBackdropItemId, {
- type: 'Backdrop',
- maxWidth: dom.getScreenWidth(),
- index: 0,
- tag: item.ParentBackdropImageTags[0]
- });
- imageLoader.lazyImage(itemBackdropElement, imgUrl);
- hasbackdrop = true;
- } else if (item.ImageTags && item.ImageTags.Primary) {
- imgUrl = apiClient.getScaledImageUrl(item.Id, {
- type: 'Primary',
- maxWidth: dom.getScreenWidth(),
- tag: item.ImageTags.Primary
- });
- imageLoader.lazyImage(itemBackdropElement, imgUrl);
- hasbackdrop = true;
- } else {
- itemBackdropElement.style.backgroundImage = '';
- }
-
- return hasbackdrop;
- }
-
- function reloadFromItem(instance, page, params, item, user) {
- const apiClient = connectionManager.getApiClient(item.ServerId);
-
- Emby.Page.setTitle('');
-
- // Start rendering the artwork first
- renderImage(page, item);
- renderLogo(page, item, apiClient);
- renderBackdrop(item);
- renderDetailPageBackdrop(page, item, apiClient);
-
- // Render the main information for the item
- page.querySelector('.detailPagePrimaryContainer').classList.add('detailRibbon');
- renderName(item, page.querySelector('.nameContainer'), params.context);
- renderDetails(page, item, apiClient, params.context);
- renderTrackSelections(page, instance, item);
-
- renderSeriesTimerEditor(page, item, apiClient, user);
- renderTimerEditor(page, item, apiClient, user);
- setInitialCollapsibleState(page, item, apiClient, params.context, user);
- const canPlay = reloadPlayButtons(page, item);
-
- if ((item.LocalTrailerCount || item.RemoteTrailers && item.RemoteTrailers.length) && playbackManager.getSupportedCommands().indexOf('PlayTrailers') !== -1) {
- hideAll(page, 'btnPlayTrailer', true);
- } else {
- hideAll(page, 'btnPlayTrailer');
- }
-
- setTrailerButtonVisibility(page, item);
-
- if (item.Type !== 'Program' || canPlay) {
- hideAll(page, 'mainDetailButtons', true);
- } else {
- hideAll(page, 'mainDetailButtons');
- }
-
- showRecordingFields(instance, page, item, user);
- const groupedVersions = (item.MediaSources || []).filter(function (g) {
- return g.Type == 'Grouping';
+ if (item.AlbumArtists) {
+ parentNameHtml.push(getArtistLinksHtml(item.AlbumArtists, item.ServerId, context));
+ parentNameLast = true;
+ } else if (item.ArtistItems && item.ArtistItems.length && item.Type === 'MusicVideo') {
+ parentNameHtml.push(getArtistLinksHtml(item.ArtistItems, item.ServerId, context));
+ parentNameLast = true;
+ } else if (item.SeriesName && item.Type === 'Episode') {
+ parentRoute = appRouter.getRouteUrl({
+ Id: item.SeriesId,
+ Name: item.SeriesName,
+ Type: 'Series',
+ IsFolder: true,
+ ServerId: item.ServerId
+ }, {
+ context: context
});
+ parentNameHtml.push('' + item.SeriesName + '');
+ } else if (item.IsSeries || item.EpisodeTitle) {
+ parentNameHtml.push(item.Name);
+ }
- if (user.Policy.IsAdministrator && groupedVersions.length) {
- page.querySelector('.btnSplitVersions').classList.remove('hide');
- } else {
- page.querySelector('.btnSplitVersions').classList.add('hide');
- }
+ if (item.SeriesName && item.Type === 'Season') {
+ parentRoute = appRouter.getRouteUrl({
+ Id: item.SeriesId,
+ Name: item.SeriesName,
+ Type: 'Series',
+ IsFolder: true,
+ ServerId: item.ServerId
+ }, {
+ context: context
+ });
+ parentNameHtml.push('' + item.SeriesName + '');
+ } else if (item.ParentIndexNumber != null && item.Type === 'Episode') {
+ parentRoute = appRouter.getRouteUrl({
+ Id: item.SeasonId,
+ Name: item.SeasonName,
+ Type: 'Season',
+ IsFolder: true,
+ ServerId: item.ServerId
+ }, {
+ context: context
+ });
+ parentNameHtml.push('' + item.SeasonName + '');
+ } else if (item.ParentIndexNumber != null && item.IsSeries) {
+ parentNameHtml.push(item.SeasonName || 'S' + item.ParentIndexNumber);
+ } else if (item.Album && item.AlbumId && (item.Type === 'MusicVideo' || item.Type === 'Audio')) {
+ parentRoute = appRouter.getRouteUrl({
+ Id: item.AlbumId,
+ Name: item.Album,
+ Type: 'MusicAlbum',
+ IsFolder: true,
+ ServerId: item.ServerId
+ }, {
+ context: context
+ });
+ parentNameHtml.push('' + item.Album + '');
+ } else if (item.Album) {
+ parentNameHtml.push(item.Album);
+ }
- if (itemContextMenu.getCommands(getContextMenuOptions(item, user)).length) {
- hideAll(page, 'btnMoreCommands', true);
- } else {
- hideAll(page, 'btnMoreCommands');
- }
+ // FIXME: This whole section needs some refactoring, so it becames easier to scale across all form factors. See GH #1022
+ let html = '';
+ const tvShowHtml = parentNameHtml[0];
+ const tvSeasonHtml = parentNameHtml[1];
- const itemBirthday = page.querySelector('#itemBirthday');
-
- if (item.Type == 'Person' && item.PremiereDate) {
- try {
- const birthday = datetime.parseISO8601Date(item.PremiereDate, true).toDateString();
- itemBirthday.classList.remove('hide');
- itemBirthday.innerHTML = globalize.translate('BirthDateValue', birthday);
- } catch (err) {
- itemBirthday.classList.add('hide');
+ if (parentNameHtml.length) {
+ if (parentNameLast) {
+ // Music
+ if (layoutManager.mobile) {
+ html = '' + parentNameHtml.join('') + '
';
+ } else {
+ html = '' + parentNameHtml.join(' - ') + '
';
}
} else {
+ html = '' + tvShowHtml + '
';
+ }
+ }
+
+ const name = itemHelper.getDisplayName(item, {
+ includeParentInfo: false
+ });
+
+ if (html && !parentNameLast) {
+ if (tvSeasonHtml) {
+ html += '' + tvSeasonHtml + ' - ' + name + '
';
+ } else {
+ html += '' + name + '
';
+ }
+ } else if (item.OriginalTitle && item.OriginalTitle != item.Name) {
+ html = '' + name + '
' + html;
+ } else {
+ html = '' + name + '
' + html;
+ }
+
+ if (item.OriginalTitle && item.OriginalTitle != item.Name) {
+ html += '' + item.OriginalTitle + '
';
+ }
+
+ container.innerHTML = html;
+
+ if (html.length) {
+ container.classList.remove('hide');
+ } else {
+ container.classList.add('hide');
+ }
+}
+
+function setTrailerButtonVisibility(page, item) {
+ if ((item.LocalTrailerCount || item.RemoteTrailers && item.RemoteTrailers.length) && playbackManager.getSupportedCommands().indexOf('PlayTrailers') !== -1) {
+ hideAll(page, 'btnPlayTrailer', true);
+ } else {
+ hideAll(page, 'btnPlayTrailer');
+ }
+}
+
+function renderBackdrop(item) {
+ if (dom.getWindowSize().innerWidth >= 1000) {
+ backdrop.setBackdrops([item]);
+ } else {
+ backdrop.clearBackdrop();
+ }
+}
+
+function renderDetailPageBackdrop(page, item, apiClient) {
+ let imgUrl;
+ let hasbackdrop = false;
+ const itemBackdropElement = page.querySelector('#itemBackdrop');
+
+ if (!layoutManager.mobile && !userSettings.detailsBanner()) {
+ return false;
+ }
+
+ if (item.BackdropImageTags && item.BackdropImageTags.length) {
+ imgUrl = apiClient.getScaledImageUrl(item.Id, {
+ type: 'Backdrop',
+ maxWidth: dom.getScreenWidth(),
+ index: 0,
+ tag: item.BackdropImageTags[0]
+ });
+ imageLoader.lazyImage(itemBackdropElement, imgUrl);
+ hasbackdrop = true;
+ } else if (item.ParentBackdropItemId && item.ParentBackdropImageTags && item.ParentBackdropImageTags.length) {
+ imgUrl = apiClient.getScaledImageUrl(item.ParentBackdropItemId, {
+ type: 'Backdrop',
+ maxWidth: dom.getScreenWidth(),
+ index: 0,
+ tag: item.ParentBackdropImageTags[0]
+ });
+ imageLoader.lazyImage(itemBackdropElement, imgUrl);
+ hasbackdrop = true;
+ } else if (item.ImageTags && item.ImageTags.Primary) {
+ imgUrl = apiClient.getScaledImageUrl(item.Id, {
+ type: 'Primary',
+ maxWidth: dom.getScreenWidth(),
+ tag: item.ImageTags.Primary
+ });
+ imageLoader.lazyImage(itemBackdropElement, imgUrl);
+ hasbackdrop = true;
+ } else {
+ itemBackdropElement.style.backgroundImage = '';
+ }
+
+ return hasbackdrop;
+}
+
+function reloadFromItem(instance, page, params, item, user) {
+ const apiClient = connectionManager.getApiClient(item.ServerId);
+
+ Emby.Page.setTitle('');
+
+ // Start rendering the artwork first
+ renderImage(page, item);
+ renderLogo(page, item, apiClient);
+ renderBackdrop(item);
+ renderDetailPageBackdrop(page, item, apiClient);
+
+ // Render the main information for the item
+ page.querySelector('.detailPagePrimaryContainer').classList.add('detailRibbon');
+ renderName(item, page.querySelector('.nameContainer'), params.context);
+ renderDetails(page, item, apiClient, params.context);
+ renderTrackSelections(page, instance, item);
+
+ renderSeriesTimerEditor(page, item, apiClient, user);
+ renderTimerEditor(page, item, apiClient, user);
+ setInitialCollapsibleState(page, item, apiClient, params.context, user);
+ const canPlay = reloadPlayButtons(page, item);
+
+ if ((item.LocalTrailerCount || item.RemoteTrailers && item.RemoteTrailers.length) && playbackManager.getSupportedCommands().indexOf('PlayTrailers') !== -1) {
+ hideAll(page, 'btnPlayTrailer', true);
+ } else {
+ hideAll(page, 'btnPlayTrailer');
+ }
+
+ setTrailerButtonVisibility(page, item);
+
+ if (item.Type !== 'Program' || canPlay) {
+ hideAll(page, 'mainDetailButtons', true);
+ } else {
+ hideAll(page, 'mainDetailButtons');
+ }
+
+ showRecordingFields(instance, page, item, user);
+ const groupedVersions = (item.MediaSources || []).filter(function (g) {
+ return g.Type == 'Grouping';
+ });
+
+ if (user.Policy.IsAdministrator && groupedVersions.length) {
+ page.querySelector('.btnSplitVersions').classList.remove('hide');
+ } else {
+ page.querySelector('.btnSplitVersions').classList.add('hide');
+ }
+
+ if (itemContextMenu.getCommands(getContextMenuOptions(item, user)).length) {
+ hideAll(page, 'btnMoreCommands', true);
+ } else {
+ hideAll(page, 'btnMoreCommands');
+ }
+
+ const itemBirthday = page.querySelector('#itemBirthday');
+
+ if (item.Type == 'Person' && item.PremiereDate) {
+ try {
+ const birthday = datetime.parseISO8601Date(item.PremiereDate, true).toDateString();
+ itemBirthday.classList.remove('hide');
+ itemBirthday.innerHTML = globalize.translate('BirthDateValue', birthday);
+ } catch (err) {
itemBirthday.classList.add('hide');
}
+ } else {
+ itemBirthday.classList.add('hide');
+ }
- const itemDeathDate = page.querySelector('#itemDeathDate');
+ const itemDeathDate = page.querySelector('#itemDeathDate');
- if (item.Type == 'Person' && item.EndDate) {
- try {
- const deathday = datetime.parseISO8601Date(item.EndDate, true).toDateString();
- itemDeathDate.classList.remove('hide');
- itemDeathDate.innerHTML = globalize.translate('DeathDateValue', deathday);
- } catch (err) {
- itemDeathDate.classList.add('hide');
- }
- } else {
+ if (item.Type == 'Person' && item.EndDate) {
+ try {
+ const deathday = datetime.parseISO8601Date(item.EndDate, true).toDateString();
+ itemDeathDate.classList.remove('hide');
+ itemDeathDate.innerHTML = globalize.translate('DeathDateValue', deathday);
+ } catch (err) {
itemDeathDate.classList.add('hide');
}
-
- const itemBirthLocation = page.querySelector('#itemBirthLocation');
-
- if (item.Type == 'Person' && item.ProductionLocations && item.ProductionLocations.length) {
- const gmap = '' + item.ProductionLocations[0] + '';
- itemBirthLocation.classList.remove('hide');
- itemBirthLocation.innerHTML = globalize.translate('BirthPlaceValue', gmap);
- } else {
- itemBirthLocation.classList.add('hide');
- }
-
- setPeopleHeader(page, item);
- loading.hide();
-
- if (item.Type === 'Book' && item.CanDownload && appHost.supports('filedownload')) {
- hideAll(page, 'btnDownload', true);
- }
-
- import('autoFocuser').then(({default: autoFocuser}) => {
- autoFocuser.autoFocus(page);
- });
+ } else {
+ itemDeathDate.classList.add('hide');
}
- function logoImageUrl(item, apiClient, options) {
- options = options || {};
- options.type = 'Logo';
+ const itemBirthLocation = page.querySelector('#itemBirthLocation');
- if (item.ImageTags && item.ImageTags.Logo) {
- options.tag = item.ImageTags.Logo;
- return apiClient.getScaledImageUrl(item.Id, options);
- }
-
- if (item.ParentLogoImageTag) {
- options.tag = item.ParentLogoImageTag;
- return apiClient.getScaledImageUrl(item.ParentLogoItemId, options);
- }
-
- return null;
+ if (item.Type == 'Person' && item.ProductionLocations && item.ProductionLocations.length) {
+ const gmap = '' + item.ProductionLocations[0] + '';
+ itemBirthLocation.classList.remove('hide');
+ itemBirthLocation.innerHTML = globalize.translate('BirthPlaceValue', gmap);
+ } else {
+ itemBirthLocation.classList.add('hide');
}
- function renderLogo(page, item, apiClient) {
- const detailLogo = page.querySelector('.detailLogo');
+ setPeopleHeader(page, item);
+ loading.hide();
- const url = logoImageUrl(item, apiClient, {});
-
- if (!layoutManager.mobile && !userSettings.enableBackdrops()) {
- detailLogo.classList.add('hide');
- } else if (url) {
- detailLogo.classList.remove('hide');
- imageLoader.setLazyImage(detailLogo, url);
- } else {
- detailLogo.classList.add('hide');
- }
+ if (item.Type === 'Book' && item.CanDownload && appHost.supports('filedownload')) {
+ hideAll(page, 'btnDownload', true);
}
- function showRecordingFields(instance, page, item, user) {
- if (!instance.currentRecordingFields) {
- const recordingFieldsElement = page.querySelector('.recordingFields');
+ import('autoFocuser').then(({ default: autoFocuser }) => {
+ autoFocuser.autoFocus(page);
+ });
+}
- if (item.Type == 'Program' && user.Policy.EnableLiveTvManagement) {
- import('recordingFields').then(({default: recordingFields}) => {
- instance.currentRecordingFields = new recordingFields({
- parent: recordingFieldsElement,
- programId: item.Id,
- serverId: item.ServerId
- });
- recordingFieldsElement.classList.remove('hide');
+function logoImageUrl(item, apiClient, options) {
+ options = options || {};
+ options.type = 'Logo';
+
+ if (item.ImageTags && item.ImageTags.Logo) {
+ options.tag = item.ImageTags.Logo;
+ return apiClient.getScaledImageUrl(item.Id, options);
+ }
+
+ if (item.ParentLogoImageTag) {
+ options.tag = item.ParentLogoImageTag;
+ return apiClient.getScaledImageUrl(item.ParentLogoItemId, options);
+ }
+
+ return null;
+}
+
+function renderLogo(page, item, apiClient) {
+ const detailLogo = page.querySelector('.detailLogo');
+
+ const url = logoImageUrl(item, apiClient, {});
+
+ if (!layoutManager.mobile && !userSettings.enableBackdrops()) {
+ detailLogo.classList.add('hide');
+ } else if (url) {
+ detailLogo.classList.remove('hide');
+ imageLoader.setLazyImage(detailLogo, url);
+ } else {
+ detailLogo.classList.add('hide');
+ }
+}
+
+function showRecordingFields(instance, page, item, user) {
+ if (!instance.currentRecordingFields) {
+ const recordingFieldsElement = page.querySelector('.recordingFields');
+
+ if (item.Type == 'Program' && user.Policy.EnableLiveTvManagement) {
+ import('recordingFields').then(({ default: recordingFields }) => {
+ instance.currentRecordingFields = new recordingFields({
+ parent: recordingFieldsElement,
+ programId: item.Id,
+ serverId: item.ServerId
});
- } else {
- recordingFieldsElement.classList.add('hide');
- recordingFieldsElement.innerHTML = '';
- }
- }
- }
-
- function renderLinks(page, item) {
- const externalLinksElem = page.querySelector('.itemExternalLinks');
-
- const links = [];
-
- if (!layoutManager.tv && item.HomePageUrl) {
- links.push(`${globalize.translate('ButtonWebsite')}`);
- }
-
- if (item.ExternalUrls) {
- for (const url of item.ExternalUrls) {
- links.push(`${url.Name}`);
- }
- }
-
- const html = [];
- if (links.length) {
- html.push(links.join(', '));
- }
-
- externalLinksElem.innerHTML = html.join(', ');
-
- if (html.length) {
- externalLinksElem.classList.remove('hide');
- } else {
- externalLinksElem.classList.add('hide');
- }
- }
-
- function renderDetailImage(elem, item, imageLoader) {
- const itemArray = [];
- itemArray.push(item);
- const cardHtml = cardBuilder.getCardsHtml(itemArray, {
- shape: 'auto',
- showTitle: false,
- centerText: true,
- overlayText: false,
- transition: false,
- disableIndicators: true,
- overlayPlayButton: true,
- action: 'play',
- width: dom.getWindowSize().innerWidth * 0.25
- });
-
- elem.innerHTML = cardHtml;
- imageLoader.lazyChildren(elem);
- }
-
- function renderImage(page, item) {
- renderDetailImage(
- page.querySelector('.detailImageContainer'),
- item,
- imageLoader
- );
- }
-
- function refreshDetailImageUserData(elem, item) {
- elem.querySelector('.detailImageProgressContainer').innerHTML = indicators.getProgressBarHtml(item);
- }
-
- function refreshImage(page, item) {
- refreshDetailImageUserData(page.querySelector('.detailImageContainer'), item);
- }
-
- function setPeopleHeader(page, item) {
- if (item.MediaType == 'Audio' || item.Type == 'MusicAlbum' || item.MediaType == 'Book' || item.MediaType == 'Photo') {
- page.querySelector('#peopleHeader').innerHTML = globalize.translate('People');
- } else {
- page.querySelector('#peopleHeader').innerHTML = globalize.translate('HeaderCastAndCrew');
- }
- }
-
- function renderNextUp(page, item, user) {
- const section = page.querySelector('.nextUpSection');
-
- if (item.Type != 'Series') {
- return void section.classList.add('hide');
- }
-
- connectionManager.getApiClient(item.ServerId).getNextUpEpisodes({
- SeriesId: item.Id,
- UserId: user.Id
- }).then(function (result) {
- if (result.Items.length) {
- section.classList.remove('hide');
- } else {
- section.classList.add('hide');
- }
-
- const html = cardBuilder.getCardsHtml({
- items: result.Items,
- shape: 'overflowBackdrop',
- showTitle: true,
- displayAsSpecial: item.Type == 'Season' && item.IndexNumber,
- overlayText: false,
- centerText: true,
- overlayPlayButton: true
+ recordingFieldsElement.classList.remove('hide');
});
- const itemsContainer = section.querySelector('.nextUpItems');
- itemsContainer.innerHTML = html;
- imageLoader.lazyChildren(itemsContainer);
- });
+ } else {
+ recordingFieldsElement.classList.add('hide');
+ recordingFieldsElement.innerHTML = '';
+ }
+ }
+}
+
+function renderLinks(page, item) {
+ const externalLinksElem = page.querySelector('.itemExternalLinks');
+
+ const links = [];
+
+ if (!layoutManager.tv && item.HomePageUrl) {
+ links.push(`${globalize.translate('ButtonWebsite')}`);
}
- function setInitialCollapsibleState(page, item, apiClient, context, user) {
- page.querySelector('.collectionItems').innerHTML = '';
+ if (item.ExternalUrls) {
+ for (const url of item.ExternalUrls) {
+ links.push(`${url.Name}`);
+ }
+ }
- if (item.Type == 'Playlist') {
- page.querySelector('#childrenCollapsible').classList.remove('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');
- renderItemsByName(page, item);
- } else if (item.IsFolder) {
- if (item.Type == 'BoxSet') {
- page.querySelector('#childrenCollapsible').classList.add('hide');
- }
+ const html = [];
+ if (links.length) {
+ html.push(links.join(', '));
+ }
- renderChildren(page, item);
+ externalLinksElem.innerHTML = html.join(', ');
+
+ if (html.length) {
+ externalLinksElem.classList.remove('hide');
+ } else {
+ externalLinksElem.classList.add('hide');
+ }
+}
+
+function renderDetailImage(elem, item, imageLoader) {
+ const itemArray = [];
+ itemArray.push(item);
+ const cardHtml = cardBuilder.getCardsHtml(itemArray, {
+ shape: 'auto',
+ showTitle: false,
+ centerText: true,
+ overlayText: false,
+ transition: false,
+ disableIndicators: true,
+ overlayPlayButton: true,
+ action: 'play',
+ width: dom.getWindowSize().innerWidth * 0.25
+ });
+
+ elem.innerHTML = cardHtml;
+ imageLoader.lazyChildren(elem);
+}
+
+function renderImage(page, item) {
+ renderDetailImage(
+ page.querySelector('.detailImageContainer'),
+ item,
+ imageLoader
+ );
+}
+
+function refreshDetailImageUserData(elem, item) {
+ elem.querySelector('.detailImageProgressContainer').innerHTML = indicators.getProgressBarHtml(item);
+}
+
+function refreshImage(page, item) {
+ refreshDetailImageUserData(page.querySelector('.detailImageContainer'), item);
+}
+
+function setPeopleHeader(page, item) {
+ if (item.MediaType == 'Audio' || item.Type == 'MusicAlbum' || item.MediaType == 'Book' || item.MediaType == 'Photo') {
+ page.querySelector('#peopleHeader').innerHTML = globalize.translate('People');
+ } else {
+ page.querySelector('#peopleHeader').innerHTML = globalize.translate('HeaderCastAndCrew');
+ }
+}
+
+function renderNextUp(page, item, user) {
+ const section = page.querySelector('.nextUpSection');
+
+ if (item.Type != 'Series') {
+ return void section.classList.add('hide');
+ }
+
+ connectionManager.getApiClient(item.ServerId).getNextUpEpisodes({
+ SeriesId: item.Id,
+ UserId: user.Id
+ }).then(function (result) {
+ if (result.Items.length) {
+ section.classList.remove('hide');
} else {
+ section.classList.add('hide');
+ }
+
+ const html = cardBuilder.getCardsHtml({
+ items: result.Items,
+ shape: 'overflowBackdrop',
+ showTitle: true,
+ displayAsSpecial: item.Type == 'Season' && item.IndexNumber,
+ overlayText: false,
+ centerText: true,
+ overlayPlayButton: true
+ });
+ const itemsContainer = section.querySelector('.nextUpItems');
+ itemsContainer.innerHTML = html;
+ imageLoader.lazyChildren(itemsContainer);
+ });
+}
+
+function setInitialCollapsibleState(page, item, apiClient, context, user) {
+ page.querySelector('.collectionItems').innerHTML = '';
+
+ if (item.Type == 'Playlist') {
+ page.querySelector('#childrenCollapsible').classList.remove('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');
+ renderItemsByName(page, item);
+ } else if (item.IsFolder) {
+ if (item.Type == 'BoxSet') {
page.querySelector('#childrenCollapsible').classList.add('hide');
}
- if (item.Type == 'Series') {
- renderSeriesSchedule(page, item);
- renderNextUp(page, item, user);
- } else {
- page.querySelector('.nextUpSection').classList.add('hide');
- }
-
- renderScenes(page, item);
-
- if (item.SpecialFeatureCount && item.SpecialFeatureCount != 0 && item.Type != 'Series') {
- page.querySelector('#specialsCollapsible').classList.remove('hide');
- renderSpecials(page, item, user);
- } else {
- page.querySelector('#specialsCollapsible').classList.add('hide');
- }
-
- renderCast(page, item);
-
- if (item.PartCount && item.PartCount > 1) {
- page.querySelector('#additionalPartsCollapsible').classList.remove('hide');
- renderAdditionalParts(page, item, user);
- } else {
- page.querySelector('#additionalPartsCollapsible').classList.add('hide');
- }
-
- if (item.Type == 'MusicAlbum') {
- renderMusicVideos(page, item, user);
- } else {
- page.querySelector('#musicVideosCollapsible').classList.add('hide');
- }
+ renderChildren(page, item);
+ } else {
+ page.querySelector('#childrenCollapsible').classList.add('hide');
}
- function toggleLineClamp(clampTarget, e) {
- const expandButton = e.target;
- const clampClassName = 'detail-clamp-text';
-
- if (clampTarget.classList.contains(clampClassName)) {
- clampTarget.classList.remove(clampClassName);
- expandButton.innerHTML = globalize.translate('ShowLess');
- } else {
- clampTarget.classList.add(clampClassName);
- expandButton.innerHTML = globalize.translate('ShowMore');
- }
+ if (item.Type == 'Series') {
+ renderSeriesSchedule(page, item);
+ renderNextUp(page, item, user);
+ } else {
+ page.querySelector('.nextUpSection').classList.add('hide');
}
- function renderOverview(page, item) {
- for (const overviewElemnt of page.querySelectorAll('.overview')) {
- const overview = item.Overview || '';
+ renderScenes(page, item);
- if (overview) {
- overviewElemnt.innerHTML = overview;
- overviewElemnt.classList.remove('hide');
- overviewElemnt.classList.add('detail-clamp-text');
+ if (item.SpecialFeatureCount && item.SpecialFeatureCount != 0 && item.Type != 'Series') {
+ page.querySelector('#specialsCollapsible').classList.remove('hide');
+ renderSpecials(page, item, user);
+ } else {
+ page.querySelector('#specialsCollapsible').classList.add('hide');
+ }
- // Grab the sibling element to control the expand state
- const expandButton = overviewElemnt.parentElement.querySelector('.overview-expand');
+ renderCast(page, item);
- // Detect if we have overflow of text. Based on this StackOverflow answer
- // https://stackoverflow.com/a/35157976
- if (Math.abs(overviewElemnt.scrollHeight - overviewElemnt.offsetHeight) > 2) {
- expandButton.classList.remove('hide');
- } else {
- expandButton.classList.add('hide');
- }
+ if (item.PartCount && item.PartCount > 1) {
+ page.querySelector('#additionalPartsCollapsible').classList.remove('hide');
+ renderAdditionalParts(page, item, user);
+ } else {
+ page.querySelector('#additionalPartsCollapsible').classList.add('hide');
+ }
- expandButton.addEventListener('click', toggleLineClamp.bind(null, overviewElemnt));
+ if (item.Type == 'MusicAlbum') {
+ renderMusicVideos(page, item, user);
+ } else {
+ page.querySelector('#musicVideosCollapsible').classList.add('hide');
+ }
+}
- for (const anchor of overviewElemnt.querySelectorAll('a')) {
- anchor.setAttribute('target', '_blank');
- }
+function toggleLineClamp(clampTarget, e) {
+ const expandButton = e.target;
+ const clampClassName = 'detail-clamp-text';
+
+ if (clampTarget.classList.contains(clampClassName)) {
+ clampTarget.classList.remove(clampClassName);
+ expandButton.innerHTML = globalize.translate('ShowLess');
+ } else {
+ clampTarget.classList.add(clampClassName);
+ expandButton.innerHTML = globalize.translate('ShowMore');
+ }
+}
+
+function renderOverview(page, item) {
+ for (const overviewElemnt of page.querySelectorAll('.overview')) {
+ const overview = item.Overview || '';
+
+ if (overview) {
+ overviewElemnt.innerHTML = overview;
+ overviewElemnt.classList.remove('hide');
+ overviewElemnt.classList.add('detail-clamp-text');
+
+ // Grab the sibling element to control the expand state
+ const expandButton = overviewElemnt.parentElement.querySelector('.overview-expand');
+
+ // Detect if we have overflow of text. Based on this StackOverflow answer
+ // https://stackoverflow.com/a/35157976
+ if (Math.abs(overviewElemnt.scrollHeight - overviewElemnt.offsetHeight) > 2) {
+ expandButton.classList.remove('hide');
} else {
- overviewElemnt.innerHTML = '';
- overviewElemnt.classList.add('hide');
+ expandButton.classList.add('hide');
}
- }
- }
- function renderGenres(page, item, context = inferContext(item)) {
- const genres = item.GenreItems || [];
- const type = context === 'music' ? 'MusicGenre' : 'Genre';
+ expandButton.addEventListener('click', toggleLineClamp.bind(null, overviewElemnt));
- const html = genres.map(function (p) {
- return '' + p.Name + '';
- }).join(', ');
-
- const genresLabel = page.querySelector('.genresLabel');
- genresLabel.innerHTML = globalize.translate(genres.length > 1 ? 'Genres' : 'Genre');
- const genresValue = page.querySelector('.genres');
- genresValue.innerHTML = html;
-
- const genresGroup = page.querySelector('.genresGroup');
- if (genres.length) {
- genresGroup.classList.remove('hide');
+ for (const anchor of overviewElemnt.querySelectorAll('a')) {
+ anchor.setAttribute('target', '_blank');
+ }
} else {
- genresGroup.classList.add('hide');
+ overviewElemnt.innerHTML = '';
+ overviewElemnt.classList.add('hide');
}
}
+}
- function renderWriter(page, item, context) {
- const writers = (item.People || []).filter(function (person) {
- return person.Type === 'Writer';
+function renderGenres(page, item, context = inferContext(item)) {
+ const genres = item.GenreItems || [];
+ const type = context === 'music' ? 'MusicGenre' : 'Genre';
+
+ const html = genres.map(function (p) {
+ return '' + p.Name + '';
+ }).join(', ');
+
+ const genresLabel = page.querySelector('.genresLabel');
+ genresLabel.innerHTML = globalize.translate(genres.length > 1 ? 'Genres' : 'Genre');
+ const genresValue = page.querySelector('.genres');
+ genresValue.innerHTML = html;
+
+ const genresGroup = page.querySelector('.genresGroup');
+ if (genres.length) {
+ genresGroup.classList.remove('hide');
+ } else {
+ genresGroup.classList.add('hide');
+ }
+}
+
+function renderWriter(page, item, context) {
+ const writers = (item.People || []).filter(function (person) {
+ return person.Type === 'Writer';
+ });
+
+ const html = writers.map(function (person) {
+ return '' + person.Name + '';
+ }).join(', ');
+
+ const writersLabel = page.querySelector('.writersLabel');
+ writersLabel.innerHTML = globalize.translate(writers.length > 1 ? 'Writers' : 'Writer');
+ const writersValue = page.querySelector('.writers');
+ writersValue.innerHTML = html;
+
+ const writersGroup = page.querySelector('.writersGroup');
+ if (writers.length) {
+ writersGroup.classList.remove('hide');
+ } else {
+ writersGroup.classList.add('hide');
+ }
+}
+
+function renderDirector(page, item, context) {
+ const directors = (item.People || []).filter(function (person) {
+ return person.Type === 'Director';
+ });
+
+ const html = directors.map(function (person) {
+ return '' + person.Name + '';
+ }).join(', ');
+
+ const directorsLabel = page.querySelector('.directorsLabel');
+ directorsLabel.innerHTML = globalize.translate(directors.length > 1 ? 'Directors' : 'Director');
+ const directorsValue = page.querySelector('.directors');
+ directorsValue.innerHTML = html;
+
+ const directorsGroup = page.querySelector('.directorsGroup');
+ if (directors.length) {
+ directorsGroup.classList.remove('hide');
+ } else {
+ directorsGroup.classList.add('hide');
+ }
+}
+
+function renderMiscInfo(page, item) {
+ const primaryItemMiscInfo = page.querySelectorAll('.itemMiscInfo-primary');
+
+ for (const miscInfo of primaryItemMiscInfo) {
+ mediaInfo.fillPrimaryMediaInfo(miscInfo, item, {
+ interactive: true,
+ episodeTitle: false,
+ subtitles: false
});
- const html = writers.map(function (person) {
- return '' + person.Name + '';
- }).join(', ');
-
- const writersLabel = page.querySelector('.writersLabel');
- writersLabel.innerHTML = globalize.translate(writers.length > 1 ? 'Writers' : 'Writer');
- const writersValue = page.querySelector('.writers');
- writersValue.innerHTML = html;
-
- const writersGroup = page.querySelector('.writersGroup');
- if (writers.length) {
- writersGroup.classList.remove('hide');
+ if (miscInfo.innerHTML && item.Type !== 'SeriesTimer') {
+ miscInfo.classList.remove('hide');
} else {
- writersGroup.classList.add('hide');
+ miscInfo.classList.add('hide');
}
}
- function renderDirector(page, item, context) {
- const directors = (item.People || []).filter(function (person) {
- return person.Type === 'Director';
+ const secondaryItemMiscInfo = page.querySelectorAll('.itemMiscInfo-secondary');
+
+ for (const miscInfo of secondaryItemMiscInfo) {
+ mediaInfo.fillSecondaryMediaInfo(miscInfo, item, {
+ interactive: true
});
- const html = directors.map(function (person) {
- return '' + person.Name + '';
- }).join(', ');
-
- const directorsLabel = page.querySelector('.directorsLabel');
- directorsLabel.innerHTML = globalize.translate(directors.length > 1 ? 'Directors' : 'Director');
- const directorsValue = page.querySelector('.directors');
- directorsValue.innerHTML = html;
-
- const directorsGroup = page.querySelector('.directorsGroup');
- if (directors.length) {
- directorsGroup.classList.remove('hide');
+ if (miscInfo.innerHTML && item.Type !== 'SeriesTimer') {
+ miscInfo.classList.remove('hide');
} else {
- directorsGroup.classList.add('hide');
+ miscInfo.classList.add('hide');
}
}
+}
- function renderMiscInfo(page, item) {
- const primaryItemMiscInfo = page.querySelectorAll('.itemMiscInfo-primary');
+function renderTagline(page, item) {
+ const taglineElement = page.querySelector('.tagline');
- for (const miscInfo of primaryItemMiscInfo) {
- mediaInfo.fillPrimaryMediaInfo(miscInfo, item, {
- interactive: true,
- episodeTitle: false,
- subtitles: false
- });
+ if (item.Taglines && item.Taglines.length) {
+ taglineElement.classList.remove('hide');
+ taglineElement.innerHTML = item.Taglines[0];
+ } else {
+ taglineElement.classList.add('hide');
+ }
+}
- if (miscInfo.innerHTML && item.Type !== 'SeriesTimer') {
- miscInfo.classList.remove('hide');
- } else {
- miscInfo.classList.add('hide');
- }
+function renderDetails(page, item, apiClient, context, isStatic) {
+ renderSimilarItems(page, item, context);
+ renderMoreFromSeason(page, item, apiClient);
+ renderMoreFromArtist(page, item, apiClient);
+ renderDirector(page, item, context);
+ renderWriter(page, item, context);
+ renderGenres(page, item, context);
+ renderChannelGuide(page, apiClient, item);
+ renderTagline(page, item);
+ renderOverview(page, item);
+ renderMiscInfo(page, item);
+ reloadUserDataButtons(page, item);
+ renderLinks(page, item);
+ renderTags(page, item);
+ renderSeriesAirTime(page, item, isStatic);
+}
+
+function enableScrollX() {
+ return browser.mobile && window.screen.availWidth <= 1000;
+}
+
+function getPortraitShape(scrollX) {
+ if (scrollX == null) {
+ scrollX = enableScrollX();
+ }
+
+ return scrollX ? 'overflowPortrait' : 'portrait';
+}
+
+function getSquareShape(scrollX) {
+ if (scrollX == null) {
+ scrollX = enableScrollX();
+ }
+
+ return scrollX ? 'overflowSquare' : 'square';
+}
+
+function renderMoreFromSeason(view, item, apiClient) {
+ const section = view.querySelector('.moreFromSeasonSection');
+
+ if (section) {
+ if (item.Type !== 'Episode' || !item.SeasonId || !item.SeriesId) {
+ return void section.classList.add('hide');
}
- const secondaryItemMiscInfo = page.querySelectorAll('.itemMiscInfo-secondary');
-
- for (const miscInfo of secondaryItemMiscInfo) {
- mediaInfo.fillSecondaryMediaInfo(miscInfo, item, {
- interactive: true
- });
-
- if (miscInfo.innerHTML && item.Type !== 'SeriesTimer') {
- miscInfo.classList.remove('hide');
- } else {
- miscInfo.classList.add('hide');
- }
- }
- }
-
- function renderTagline(page, item) {
- const taglineElement = page.querySelector('.tagline');
-
- if (item.Taglines && item.Taglines.length) {
- taglineElement.classList.remove('hide');
- taglineElement.innerHTML = item.Taglines[0];
- } else {
- taglineElement.classList.add('hide');
- }
- }
-
- function renderDetails(page, item, apiClient, context, isStatic) {
- renderSimilarItems(page, item, context);
- renderMoreFromSeason(page, item, apiClient);
- renderMoreFromArtist(page, item, apiClient);
- renderDirector(page, item, context);
- renderWriter(page, item, context);
- renderGenres(page, item, context);
- renderChannelGuide(page, apiClient, item);
- renderTagline(page, item);
- renderOverview(page, item);
- renderMiscInfo(page, item);
- reloadUserDataButtons(page, item);
- renderLinks(page, item);
- renderTags(page, item);
- renderSeriesAirTime(page, item, isStatic);
- }
-
- function enableScrollX() {
- return browser.mobile && window.screen.availWidth <= 1000;
- }
-
- function getPortraitShape(scrollX) {
- if (scrollX == null) {
- scrollX = enableScrollX();
- }
-
- return scrollX ? 'overflowPortrait' : 'portrait';
- }
-
- function getSquareShape(scrollX) {
- if (scrollX == null) {
- scrollX = enableScrollX();
- }
-
- return scrollX ? 'overflowSquare' : 'square';
- }
-
- function renderMoreFromSeason(view, item, apiClient) {
- const section = view.querySelector('.moreFromSeasonSection');
-
- if (section) {
- if (item.Type !== 'Episode' || !item.SeasonId || !item.SeriesId) {
+ const userId = apiClient.getCurrentUserId();
+ apiClient.getEpisodes(item.SeriesId, {
+ SeasonId: item.SeasonId,
+ UserId: userId,
+ Fields: 'ItemCounts,PrimaryImageAspectRatio,BasicSyncInfo,CanDelete,MediaSourceCount'
+ }).then(function (result) {
+ if (result.Items.length < 2) {
return void section.classList.add('hide');
}
- const userId = apiClient.getCurrentUserId();
- apiClient.getEpisodes(item.SeriesId, {
- SeasonId: item.SeasonId,
- UserId: userId,
- Fields: 'ItemCounts,PrimaryImageAspectRatio,BasicSyncInfo,CanDelete,MediaSourceCount'
- }).then(function (result) {
- if (result.Items.length < 2) {
- return void section.classList.add('hide');
- }
-
- section.classList.remove('hide');
- section.querySelector('h2').innerHTML = globalize.translate('MoreFromValue', item.SeasonName);
- const itemsContainer = section.querySelector('.itemsContainer');
- cardBuilder.buildCards(result.Items, {
- parentContainer: section,
- itemsContainer: itemsContainer,
- shape: 'autooverflow',
- sectionTitleTagName: 'h2',
- scalable: true,
- showTitle: true,
- overlayText: false,
- centerText: true,
- includeParentInfoInTitle: false,
- allowBottomPadding: false
- });
- const card = itemsContainer.querySelector('.card[data-id="' + item.Id + '"]');
-
- if (card) {
- setTimeout(function () {
- section.querySelector('.emby-scroller').toStart(card.previousSibling || card, true);
- }, 100);
- }
+ section.classList.remove('hide');
+ section.querySelector('h2').innerHTML = globalize.translate('MoreFromValue', item.SeasonName);
+ const itemsContainer = section.querySelector('.itemsContainer');
+ cardBuilder.buildCards(result.Items, {
+ parentContainer: section,
+ itemsContainer: itemsContainer,
+ shape: 'autooverflow',
+ sectionTitleTagName: 'h2',
+ scalable: true,
+ showTitle: true,
+ overlayText: false,
+ centerText: true,
+ includeParentInfoInTitle: false,
+ allowBottomPadding: false
});
- }
+ const card = itemsContainer.querySelector('.card[data-id="' + item.Id + '"]');
+
+ if (card) {
+ setTimeout(function () {
+ section.querySelector('.emby-scroller').toStart(card.previousSibling || card, true);
+ }, 100);
+ }
+ });
}
+}
- function renderMoreFromArtist(view, item, apiClient) {
- const section = view.querySelector('.moreFromArtistSection');
+function renderMoreFromArtist(view, item, apiClient) {
+ const section = view.querySelector('.moreFromArtistSection');
- if (section) {
- if (item.Type === 'MusicArtist') {
- if (!apiClient.isMinServerVersion('3.4.1.19')) {
- return void section.classList.add('hide');
- }
- } else if (item.Type !== 'MusicAlbum' || !item.AlbumArtists || !item.AlbumArtists.length) {
+ if (section) {
+ if (item.Type === 'MusicArtist') {
+ if (!apiClient.isMinServerVersion('3.4.1.19')) {
+ return void section.classList.add('hide');
+ }
+ } else if (item.Type !== 'MusicAlbum' || !item.AlbumArtists || !item.AlbumArtists.length) {
+ return void section.classList.add('hide');
+ }
+
+ const query = {
+ IncludeItemTypes: 'MusicAlbum',
+ Recursive: true,
+ ExcludeItemIds: item.Id,
+ SortBy: 'ProductionYear,SortName',
+ SortOrder: 'Descending'
+ };
+
+ if (item.Type === 'MusicArtist') {
+ query.ContributingArtistIds = item.Id;
+ } else if (apiClient.isMinServerVersion('3.4.1.18')) {
+ query.AlbumArtistIds = item.AlbumArtists[0].Id;
+ } else {
+ query.ArtistIds = item.AlbumArtists[0].Id;
+ }
+
+ apiClient.getItems(apiClient.getCurrentUserId(), query).then(function (result) {
+ if (!result.Items.length) {
return void section.classList.add('hide');
}
- const query = {
- IncludeItemTypes: 'MusicAlbum',
- Recursive: true,
- ExcludeItemIds: item.Id,
- SortBy: 'ProductionYear,SortName',
- SortOrder: 'Descending'
- };
+ section.classList.remove('hide');
if (item.Type === 'MusicArtist') {
- query.ContributingArtistIds = item.Id;
- } else if (apiClient.isMinServerVersion('3.4.1.18')) {
- query.AlbumArtistIds = item.AlbumArtists[0].Id;
+ section.querySelector('h2').innerHTML = globalize.translate('HeaderAppearsOn');
} else {
- query.ArtistIds = item.AlbumArtists[0].Id;
+ section.querySelector('h2').innerHTML = globalize.translate('MoreFromValue', item.AlbumArtists[0].Name);
}
- apiClient.getItems(apiClient.getCurrentUserId(), query).then(function (result) {
- if (!result.Items.length) {
- return void section.classList.add('hide');
- }
-
- section.classList.remove('hide');
-
- if (item.Type === 'MusicArtist') {
- section.querySelector('h2').innerHTML = globalize.translate('HeaderAppearsOn');
- } else {
- section.querySelector('h2').innerHTML = globalize.translate('MoreFromValue', item.AlbumArtists[0].Name);
- }
-
- cardBuilder.buildCards(result.Items, {
- parentContainer: section,
- itemsContainer: section.querySelector('.itemsContainer'),
- shape: 'autooverflow',
- sectionTitleTagName: 'h2',
- scalable: true,
- coverImage: item.Type === 'MusicArtist' || item.Type === 'MusicAlbum',
- showTitle: true,
- showParentTitle: false,
- centerText: true,
- overlayText: false,
- overlayPlayButton: true,
- showYear: true
- });
+ cardBuilder.buildCards(result.Items, {
+ parentContainer: section,
+ itemsContainer: section.querySelector('.itemsContainer'),
+ shape: 'autooverflow',
+ sectionTitleTagName: 'h2',
+ scalable: true,
+ coverImage: item.Type === 'MusicArtist' || item.Type === 'MusicAlbum',
+ showTitle: true,
+ showParentTitle: false,
+ centerText: true,
+ overlayText: false,
+ overlayPlayButton: true,
+ showYear: true
});
- }
+ });
}
+}
- function renderSimilarItems(page, item, context) {
- const similarCollapsible = page.querySelector('#similarCollapsible');
+function renderSimilarItems(page, item, context) {
+ const similarCollapsible = page.querySelector('#similarCollapsible');
- if (similarCollapsible) {
- if (item.Type != 'Movie' && item.Type != 'Trailer' && item.Type != 'Series' && item.Type != 'Program' && item.Type != 'Recording' && item.Type != 'MusicAlbum' && item.Type != 'MusicArtist' && item.Type != 'Playlist') {
+ if (similarCollapsible) {
+ if (item.Type != 'Movie' && item.Type != 'Trailer' && item.Type != 'Series' && item.Type != 'Program' && item.Type != 'Recording' && item.Type != 'MusicAlbum' && item.Type != 'MusicArtist' && item.Type != 'Playlist') {
+ return void similarCollapsible.classList.add('hide');
+ }
+
+ similarCollapsible.classList.remove('hide');
+ const apiClient = connectionManager.getApiClient(item.ServerId);
+ const options = {
+ userId: apiClient.getCurrentUserId(),
+ limit: 12,
+ fields: 'PrimaryImageAspectRatio,UserData,CanDelete'
+ };
+
+ if (item.Type == 'MusicAlbum' && item.AlbumArtists && item.AlbumArtists.length) {
+ options.ExcludeArtistIds = item.AlbumArtists[0].Id;
+ }
+
+ apiClient.getSimilarItems(item.Id, options).then(function (result) {
+ if (!result.Items.length) {
return void similarCollapsible.classList.add('hide');
}
similarCollapsible.classList.remove('hide');
- const apiClient = connectionManager.getApiClient(item.ServerId);
- const options = {
- userId: apiClient.getCurrentUserId(),
- limit: 12,
- fields: 'PrimaryImageAspectRatio,UserData,CanDelete'
- };
-
- if (item.Type == 'MusicAlbum' && item.AlbumArtists && item.AlbumArtists.length) {
- options.ExcludeArtistIds = item.AlbumArtists[0].Id;
- }
-
- apiClient.getSimilarItems(item.Id, options).then(function (result) {
- if (!result.Items.length) {
- return void similarCollapsible.classList.add('hide');
- }
-
- similarCollapsible.classList.remove('hide');
- let html = '';
- html += cardBuilder.getCardsHtml({
- items: result.Items,
- shape: 'autooverflow',
- showParentTitle: item.Type == 'MusicAlbum',
- centerText: true,
- showTitle: true,
- context: context,
- lazy: true,
- showDetailsMenu: true,
- coverImage: item.Type == 'MusicAlbum' || item.Type == 'MusicArtist',
- overlayPlayButton: true,
- overlayText: false,
- showYear: item.Type === 'Movie' || item.Type === 'Trailer' || item.Type === 'Series'
- });
- const similarContent = similarCollapsible.querySelector('.similarContent');
- similarContent.innerHTML = html;
- imageLoader.lazyChildren(similarContent);
- });
- }
- }
-
- function renderSeriesAirTime(page, item, isStatic) {
- const seriesAirTime = page.querySelector('#seriesAirTime');
- if (item.Type != 'Series') {
- seriesAirTime.classList.add('hide');
- return;
- }
- let html = '';
- if (item.AirDays && item.AirDays.length) {
- if (item.AirDays.length == 7) {
- html += 'daily';
- } else {
- html += item.AirDays.map(function (a) {
- return a + 's';
- }).join(',');
- }
- }
- if (item.AirTime) {
- html += ' at ' + item.AirTime;
- }
- if (item.Studios.length) {
- if (isStatic) {
- html += ' on ' + item.Studios[0].Name;
- } else {
- const context = inferContext(item);
- const href = appRouter.getRouteUrl(item.Studios[0], {
- context: context,
- itemType: 'Studio',
- serverId: item.ServerId
- });
- html += ' on ' + item.Studios[0].Name + '';
- }
- }
- if (html) {
- html = (item.Status == 'Ended' ? 'Aired ' : 'Airs ') + html;
- seriesAirTime.innerHTML = html;
- seriesAirTime.classList.remove('hide');
- } else {
- seriesAirTime.classList.add('hide');
- }
- }
-
- function renderTags(page, item) {
- const itemTags = page.querySelector('.itemTags');
- const tagElements = [];
- let tags = item.Tags || [];
-
- if (item.Type === 'Program') {
- tags = [];
- }
-
- for (let i = 0, length = tags.length; i < length; i++) {
- tagElements.push(tags[i]);
- }
-
- if (tagElements.length) {
- itemTags.innerHTML = globalize.translate('TagsValue', tagElements.join(', '));
- itemTags.classList.remove('hide');
- } else {
- itemTags.innerHTML = '';
- itemTags.classList.add('hide');
- }
- }
-
- function renderChildren(page, item) {
- let fields = 'ItemCounts,PrimaryImageAspectRatio,BasicSyncInfo,CanDelete,MediaSourceCount';
- const query = {
- ParentId: item.Id,
- Fields: fields
- };
-
- if (item.Type !== 'BoxSet') {
- query.SortBy = 'SortName';
- }
-
- let promise;
- const apiClient = connectionManager.getApiClient(item.ServerId);
- const userId = apiClient.getCurrentUserId();
-
- if (item.Type == 'Series') {
- promise = apiClient.getSeasons(item.Id, {
- userId: userId,
- Fields: fields
- });
- } else if (item.Type == 'Season') {
- fields += ',Overview';
- promise = apiClient.getEpisodes(item.SeriesId, {
- seasonId: item.Id,
- userId: userId,
- Fields: fields
- });
- } else if (item.Type == 'MusicArtist') {
- query.SortBy = 'ProductionYear,SortName';
- }
-
- promise = promise || apiClient.getItems(apiClient.getCurrentUserId(), query);
- promise.then(function (result) {
let html = '';
- let scrollX = false;
- let isList = false;
- const childrenItemsContainer = page.querySelector('.childrenItemsContainer');
+ html += cardBuilder.getCardsHtml({
+ items: result.Items,
+ shape: 'autooverflow',
+ showParentTitle: item.Type == 'MusicAlbum',
+ centerText: true,
+ showTitle: true,
+ context: context,
+ lazy: true,
+ showDetailsMenu: true,
+ coverImage: item.Type == 'MusicAlbum' || item.Type == 'MusicArtist',
+ overlayPlayButton: true,
+ overlayText: false,
+ showYear: item.Type === 'Movie' || item.Type === 'Trailer' || item.Type === 'Series'
+ });
+ const similarContent = similarCollapsible.querySelector('.similarContent');
+ similarContent.innerHTML = html;
+ imageLoader.lazyChildren(similarContent);
+ });
+ }
+}
- if (item.Type == 'MusicAlbum') {
- html = listView.getListViewHtml({
- items: result.Items,
- smallIcon: true,
- showIndex: true,
- index: 'disc',
- showIndexNumberLeft: true,
- playFromHere: true,
- action: 'playallfromhere',
- image: false,
- artist: 'auto',
- containerAlbumArtists: item.AlbumArtists
- });
+function renderSeriesAirTime(page, item, isStatic) {
+ const seriesAirTime = page.querySelector('#seriesAirTime');
+ if (item.Type != 'Series') {
+ seriesAirTime.classList.add('hide');
+ return;
+ }
+ let html = '';
+ if (item.AirDays && item.AirDays.length) {
+ if (item.AirDays.length == 7) {
+ html += 'daily';
+ } else {
+ html += item.AirDays.map(function (a) {
+ return a + 's';
+ }).join(',');
+ }
+ }
+ if (item.AirTime) {
+ html += ' at ' + item.AirTime;
+ }
+ if (item.Studios.length) {
+ if (isStatic) {
+ html += ' on ' + item.Studios[0].Name;
+ } else {
+ const context = inferContext(item);
+ const href = appRouter.getRouteUrl(item.Studios[0], {
+ context: context,
+ itemType: 'Studio',
+ serverId: item.ServerId
+ });
+ html += ' on ' + item.Studios[0].Name + '';
+ }
+ }
+ if (html) {
+ html = (item.Status == 'Ended' ? 'Aired ' : 'Airs ') + html;
+ seriesAirTime.innerHTML = html;
+ seriesAirTime.classList.remove('hide');
+ } else {
+ seriesAirTime.classList.add('hide');
+ }
+}
+
+function renderTags(page, item) {
+ const itemTags = page.querySelector('.itemTags');
+ const tagElements = [];
+ let tags = item.Tags || [];
+
+ if (item.Type === 'Program') {
+ tags = [];
+ }
+
+ for (let i = 0, length = tags.length; i < length; i++) {
+ tagElements.push(tags[i]);
+ }
+
+ if (tagElements.length) {
+ itemTags.innerHTML = globalize.translate('TagsValue', tagElements.join(', '));
+ itemTags.classList.remove('hide');
+ } else {
+ itemTags.innerHTML = '';
+ itemTags.classList.add('hide');
+ }
+}
+
+function renderChildren(page, item) {
+ let fields = 'ItemCounts,PrimaryImageAspectRatio,BasicSyncInfo,CanDelete,MediaSourceCount';
+ const query = {
+ ParentId: item.Id,
+ Fields: fields
+ };
+
+ if (item.Type !== 'BoxSet') {
+ query.SortBy = 'SortName';
+ }
+
+ let promise;
+ const apiClient = connectionManager.getApiClient(item.ServerId);
+ const userId = apiClient.getCurrentUserId();
+
+ if (item.Type == 'Series') {
+ promise = apiClient.getSeasons(item.Id, {
+ userId: userId,
+ Fields: fields
+ });
+ } else if (item.Type == 'Season') {
+ fields += ',Overview';
+ promise = apiClient.getEpisodes(item.SeriesId, {
+ seasonId: item.Id,
+ userId: userId,
+ Fields: fields
+ });
+ } else if (item.Type == 'MusicArtist') {
+ query.SortBy = 'ProductionYear,SortName';
+ }
+
+ promise = promise || apiClient.getItems(apiClient.getCurrentUserId(), query);
+ promise.then(function (result) {
+ let html = '';
+ let scrollX = false;
+ let isList = false;
+ const childrenItemsContainer = page.querySelector('.childrenItemsContainer');
+
+ if (item.Type == 'MusicAlbum') {
+ html = listView.getListViewHtml({
+ items: result.Items,
+ smallIcon: true,
+ showIndex: true,
+ index: 'disc',
+ showIndexNumberLeft: true,
+ playFromHere: true,
+ action: 'playallfromhere',
+ image: false,
+ artist: 'auto',
+ containerAlbumArtists: item.AlbumArtists
+ });
+ isList = true;
+ } else if (item.Type == 'Series') {
+ scrollX = enableScrollX();
+ html = cardBuilder.getCardsHtml({
+ items: result.Items,
+ shape: 'overflowPortrait',
+ showTitle: true,
+ centerText: true,
+ lazy: true,
+ overlayPlayButton: true,
+ allowBottomPadding: !scrollX
+ });
+ } else if (item.Type == 'Season' || item.Type == 'Episode') {
+ if (item.Type !== 'Episode') {
isList = true;
- } else if (item.Type == 'Series') {
- scrollX = enableScrollX();
+ }
+ scrollX = item.Type == 'Episode';
+ if (result.Items.length < 2 && item.Type === 'Episode') {
+ return;
+ }
+
+ if (item.Type === 'Episode') {
html = cardBuilder.getCardsHtml({
items: result.Items,
- shape: 'overflowPortrait',
+ shape: 'overflowBackdrop',
showTitle: true,
- centerText: true,
+ displayAsSpecial: item.Type == 'Season' && item.IndexNumber,
+ playFromHere: true,
+ overlayText: true,
lazy: true,
+ showDetailsMenu: true,
overlayPlayButton: true,
- allowBottomPadding: !scrollX
+ allowBottomPadding: !scrollX,
+ includeParentInfoInTitle: false
+ });
+ } else if (item.Type === 'Season') {
+ html = listView.getListViewHtml({
+ items: result.Items,
+ showIndexNumber: false,
+ enableOverview: true,
+ enablePlayedButton: layoutManager.mobile ? false : true,
+ infoButton: layoutManager.mobile ? false : true,
+ imageSize: 'large',
+ enableSideMediaInfo: false,
+ highlight: false,
+ action: !layoutManager.desktop ? 'link' : 'none',
+ imagePlayButton: true,
+ includeParentInfoInTitle: false
});
- } else if (item.Type == 'Season' || item.Type == 'Episode') {
- if (item.Type !== 'Episode') {
- isList = true;
- }
- scrollX = item.Type == 'Episode';
- if (result.Items.length < 2 && item.Type === 'Episode') {
- return;
- }
-
- if (item.Type === 'Episode') {
- html = cardBuilder.getCardsHtml({
- items: result.Items,
- shape: 'overflowBackdrop',
- showTitle: true,
- displayAsSpecial: item.Type == 'Season' && item.IndexNumber,
- playFromHere: true,
- overlayText: true,
- lazy: true,
- showDetailsMenu: true,
- overlayPlayButton: true,
- allowBottomPadding: !scrollX,
- includeParentInfoInTitle: false
- });
- } else if (item.Type === 'Season') {
- html = listView.getListViewHtml({
- items: result.Items,
- showIndexNumber: false,
- enableOverview: true,
- enablePlayedButton: layoutManager.mobile ? false : true,
- infoButton: layoutManager.mobile ? false : true,
- imageSize: 'large',
- enableSideMediaInfo: false,
- highlight: false,
- action: !layoutManager.desktop ? 'link' : 'none',
- imagePlayButton: true,
- includeParentInfoInTitle: false
- });
- }
}
+ }
- if (item.Type !== 'BoxSet') {
- page.querySelector('#childrenCollapsible').classList.remove('hide');
- }
- if (scrollX) {
- childrenItemsContainer.classList.add('scrollX');
- childrenItemsContainer.classList.add('hiddenScrollX');
+ if (item.Type !== 'BoxSet') {
+ page.querySelector('#childrenCollapsible').classList.remove('hide');
+ }
+ if (scrollX) {
+ childrenItemsContainer.classList.add('scrollX');
+ childrenItemsContainer.classList.add('hiddenScrollX');
+ childrenItemsContainer.classList.remove('vertical-wrap');
+ childrenItemsContainer.classList.remove('vertical-list');
+ } else {
+ childrenItemsContainer.classList.remove('scrollX');
+ childrenItemsContainer.classList.remove('hiddenScrollX');
+ childrenItemsContainer.classList.remove('smoothScrollX');
+ if (isList) {
+ childrenItemsContainer.classList.add('vertical-list');
childrenItemsContainer.classList.remove('vertical-wrap');
- childrenItemsContainer.classList.remove('vertical-list');
} else {
- childrenItemsContainer.classList.remove('scrollX');
- childrenItemsContainer.classList.remove('hiddenScrollX');
- childrenItemsContainer.classList.remove('smoothScrollX');
- if (isList) {
- childrenItemsContainer.classList.add('vertical-list');
- childrenItemsContainer.classList.remove('vertical-wrap');
- } else {
- childrenItemsContainer.classList.add('vertical-wrap');
- childrenItemsContainer.classList.remove('vertical-list');
- }
+ childrenItemsContainer.classList.add('vertical-wrap');
+ childrenItemsContainer.classList.remove('vertical-list');
}
- if (layoutManager.mobile) {
- childrenItemsContainer.classList.remove('padded-right');
- }
- childrenItemsContainer.innerHTML = html;
- imageLoader.lazyChildren(childrenItemsContainer);
- if (item.Type == 'BoxSet') {
- const collectionItemTypes = [{
- name: globalize.translate('HeaderVideos'),
- mediaType: 'Video'
- }, {
- name: globalize.translate('Series'),
- type: 'Series'
- }, {
- name: globalize.translate('Albums'),
- type: 'MusicAlbum'
- }, {
- name: globalize.translate('Books'),
- type: 'Book'
- }];
- renderCollectionItems(page, item, collectionItemTypes, result.Items);
- }
- });
-
- if (item.Type == 'Season') {
- page.querySelector('#childrenTitle').innerHTML = globalize.translate('Episodes');
- } else if (item.Type == 'Series') {
- page.querySelector('#childrenTitle').innerHTML = globalize.translate('HeaderSeasons');
- } else if (item.Type == 'MusicAlbum') {
- page.querySelector('#childrenTitle').innerHTML = globalize.translate('HeaderTracks');
- } else {
- page.querySelector('#childrenTitle').innerHTML = globalize.translate('Items');
}
-
- if (item.Type == 'MusicAlbum' || item.Type == 'Season') {
- page.querySelector('.childrenSectionHeader').classList.add('hide');
- page.querySelector('#childrenCollapsible').classList.add('verticalSection-extrabottompadding');
- } else {
- page.querySelector('.childrenSectionHeader').classList.remove('hide');
+ if (layoutManager.mobile) {
+ childrenItemsContainer.classList.remove('padded-right');
}
+ childrenItemsContainer.innerHTML = html;
+ imageLoader.lazyChildren(childrenItemsContainer);
+ if (item.Type == 'BoxSet') {
+ const collectionItemTypes = [{
+ name: globalize.translate('HeaderVideos'),
+ mediaType: 'Video'
+ }, {
+ name: globalize.translate('Series'),
+ type: 'Series'
+ }, {
+ name: globalize.translate('Albums'),
+ type: 'MusicAlbum'
+ }, {
+ name: globalize.translate('Books'),
+ type: 'Book'
+ }];
+ renderCollectionItems(page, item, collectionItemTypes, result.Items);
+ }
+ });
+
+ if (item.Type == 'Season') {
+ page.querySelector('#childrenTitle').innerHTML = globalize.translate('Episodes');
+ } else if (item.Type == 'Series') {
+ page.querySelector('#childrenTitle').innerHTML = globalize.translate('HeaderSeasons');
+ } else if (item.Type == 'MusicAlbum') {
+ page.querySelector('#childrenTitle').innerHTML = globalize.translate('HeaderTracks');
+ } else {
+ page.querySelector('#childrenTitle').innerHTML = globalize.translate('Items');
}
- function renderItemsByName(page, item) {
- import('scripts/itembynamedetailpage').then(() => {
- window.ItemsByName.renderItems(page, item);
- });
+ if (item.Type == 'MusicAlbum' || item.Type == 'Season') {
+ page.querySelector('.childrenSectionHeader').classList.add('hide');
+ page.querySelector('#childrenCollapsible').classList.add('verticalSection-extrabottompadding');
+ } else {
+ page.querySelector('.childrenSectionHeader').classList.remove('hide');
}
+}
- function renderPlaylistItems(page, item) {
- import('scripts/playlistedit').then(() => {
- PlaylistViewer.render(page, item);
- });
- }
+function renderItemsByName(page, item) {
+ import('scripts/itembynamedetailpage').then(() => {
+ window.ItemsByName.renderItems(page, item);
+ });
+}
- function renderProgramsForChannel(page, result) {
- let html = '';
- let currentItems = [];
- let currentStartDate = null;
+function renderPlaylistItems(page, item) {
+ import('scripts/playlistedit').then(() => {
+ PlaylistViewer.render(page, item);
+ });
+}
- for (let i = 0, length = result.Items.length; i < length; i++) {
- const item = result.Items[i];
- const itemStartDate = datetime.parseISO8601Date(item.StartDate);
+function renderProgramsForChannel(page, result) {
+ let html = '';
+ let currentItems = [];
+ let currentStartDate = null;
- if (!(currentStartDate && currentStartDate.toDateString() === itemStartDate.toDateString())) {
- if (currentItems.length) {
- html += '';
- html += '
' + datetime.toLocaleDateString(currentStartDate, {
- weekday: 'long',
- month: 'long',
- day: 'numeric'
- }) + '
';
- html += '
' + listView.getListViewHtml({
- items: currentItems,
- enableUserDataButtons: false,
- showParentTitle: true,
- image: false,
- showProgramTime: true,
- mediaInfo: false,
- parentTitleWithTitle: true
- }) + '
';
- }
+ for (let i = 0, length = result.Items.length; i < length; i++) {
+ const item = result.Items[i];
+ const itemStartDate = datetime.parseISO8601Date(item.StartDate);
- currentStartDate = itemStartDate;
- currentItems = [];
+ if (!(currentStartDate && currentStartDate.toDateString() === itemStartDate.toDateString())) {
+ if (currentItems.length) {
+ html += '';
+ html += '
' + datetime.toLocaleDateString(currentStartDate, {
+ weekday: 'long',
+ month: 'long',
+ day: 'numeric'
+ }) + '
';
+ html += '
' + listView.getListViewHtml({
+ items: currentItems,
+ enableUserDataButtons: false,
+ showParentTitle: true,
+ image: false,
+ showProgramTime: true,
+ mediaInfo: false,
+ parentTitleWithTitle: true
+ }) + '
';
}
- currentItems.push(item);
+ currentStartDate = itemStartDate;
+ currentItems = [];
}
- if (currentItems.length) {
- html += '';
- html += '
' + datetime.toLocaleDateString(currentStartDate, {
- weekday: 'long',
- month: 'long',
- day: 'numeric'
- }) + '
';
- html += '
' + listView.getListViewHtml({
- items: currentItems,
- enableUserDataButtons: false,
- showParentTitle: true,
- image: false,
- showProgramTime: true,
- mediaInfo: false,
- parentTitleWithTitle: true
- }) + '
';
- }
-
- page.querySelector('.programGuide').innerHTML = html;
+ currentItems.push(item);
}
- function renderChannelGuide(page, apiClient, item) {
- if (item.Type === 'TvChannel') {
- page.querySelector('.programGuideSection').classList.remove('hide');
- apiClient.getLiveTvPrograms({
- ChannelIds: item.Id,
- UserId: apiClient.getCurrentUserId(),
- HasAired: false,
- SortBy: 'StartDate',
- EnableTotalRecordCount: false,
- EnableImages: false,
- ImageTypeLimit: 0,
- EnableUserData: false
- }).then(function (result) {
- renderProgramsForChannel(page, result);
- });
- }
+ if (currentItems.length) {
+ html += '';
+ html += '
' + datetime.toLocaleDateString(currentStartDate, {
+ weekday: 'long',
+ month: 'long',
+ day: 'numeric'
+ }) + '
';
+ html += '
' + listView.getListViewHtml({
+ items: currentItems,
+ enableUserDataButtons: false,
+ showParentTitle: true,
+ image: false,
+ showProgramTime: true,
+ mediaInfo: false,
+ parentTitleWithTitle: true
+ }) + '
';
}
- function renderSeriesSchedule(page, item) {
- const apiClient = connectionManager.getApiClient(item.ServerId);
+ page.querySelector('.programGuide').innerHTML = html;
+}
+
+function renderChannelGuide(page, apiClient, item) {
+ if (item.Type === 'TvChannel') {
+ page.querySelector('.programGuideSection').classList.remove('hide');
apiClient.getLiveTvPrograms({
+ ChannelIds: item.Id,
UserId: apiClient.getCurrentUserId(),
HasAired: false,
SortBy: 'StartDate',
EnableTotalRecordCount: false,
EnableImages: false,
ImageTypeLimit: 0,
- Limit: 50,
- EnableUserData: false,
- LibrarySeriesId: item.Id
+ EnableUserData: false
}).then(function (result) {
- if (result.Items.length) {
- page.querySelector('#seriesScheduleSection').classList.remove('hide');
- } else {
- page.querySelector('#seriesScheduleSection').classList.add('hide');
- }
-
- page.querySelector('#seriesScheduleList').innerHTML = listView.getListViewHtml({
- items: result.Items,
- enableUserDataButtons: false,
- showParentTitle: false,
- image: false,
- showProgramDateTime: true,
- mediaInfo: false,
- showTitle: true,
- moreButton: false,
- action: 'programdialog'
- });
- loading.hide();
+ renderProgramsForChannel(page, result);
});
}
+}
- function inferContext(item) {
- if (item.Type === 'Movie' || item.Type === 'BoxSet') {
- return 'movies';
- }
-
- if (item.Type === 'Series' || item.Type === 'Season' || item.Type === 'Episode') {
- return 'tvshows';
- }
-
- if (item.Type === 'MusicArtist' || item.Type === 'MusicAlbum' || item.Type === 'Audio' || item.Type === 'AudioBook') {
- return 'music';
- }
-
- if (item.Type === 'Program') {
- return 'livetv';
- }
-
- return null;
- }
-
- function filterItemsByCollectionItemType(items, typeInfo) {
- return items.filter(function (item) {
- if (typeInfo.mediaType) {
- return item.MediaType == typeInfo.mediaType;
- }
-
- return item.Type == typeInfo.type;
- });
- }
-
- function canPlaySomeItemInCollection(items) {
- let i = 0;
-
- for (let length = items.length; i < length; i++) {
- if (playbackManager.canPlay(items[i])) {
- return true;
- }
- }
-
- return false;
- }
-
- function renderCollectionItems(page, parentItem, types, items) {
- page.querySelector('.collectionItems').classList.remove('hide');
- page.querySelector('.collectionItems').innerHTML = '';
-
- for (const type of types) {
- const typeItems = filterItemsByCollectionItemType(items, type);
-
- if (typeItems.length) {
- renderCollectionItemType(page, parentItem, type, typeItems);
- }
- }
-
- const otherType = {
- name: globalize.translate('HeaderOtherItems')
- };
- const otherTypeItems = items.filter(function (curr) {
- return !types.filter(function (t) {
- return filterItemsByCollectionItemType([curr], t).length > 0;
- }).length;
- });
-
- if (otherTypeItems.length) {
- renderCollectionItemType(page, parentItem, otherType, otherTypeItems);
- }
-
- if (!items.length) {
- renderCollectionItemType(page, parentItem, {
- name: globalize.translate('Items')
- }, items);
- }
-
- const containers = page.querySelectorAll('.collectionItemsContainer');
-
- const notifyRefreshNeeded = function () {
- renderChildren(page, parentItem);
- };
-
- for (const container of containers) {
- container.notifyRefreshNeeded = notifyRefreshNeeded;
- }
-
- // if nothing in the collection can be played hide play and shuffle buttons
- if (!canPlaySomeItemInCollection(items)) {
- hideAll(page, 'btnPlay', false);
- hideAll(page, 'btnShuffle', false);
- }
-
- // HACK: Call autoFocuser again because btnPlay may be hidden, but focused by reloadFromItem
- // FIXME: Sometimes focus does not move until all (?) sections are loaded
- import('autoFocuser').then(({default: autoFocuser}) => {
- autoFocuser.autoFocus(page);
- });
- }
-
- function renderCollectionItemType(page, parentItem, type, items) {
- let html = '';
- html += '';
- html += '
';
- html += '
';
- html += '' + type.name + '';
- html += '
';
- html += '';
- html += '
';
- const shape = type.type == 'MusicAlbum' ? getSquareShape(false) : getPortraitShape(false);
- html += cardBuilder.getCardsHtml({
- items: items,
- shape: shape,
- showTitle: true,
- showYear: type.mediaType === 'Video' || type.type === 'Series',
- centerText: true,
- lazy: true,
- showDetailsMenu: true,
- overlayMoreButton: true,
- showAddToCollection: false,
- showRemoveFromCollection: true,
- collectionId: parentItem.Id
- });
- html += '
';
- html += '
';
- const collectionItems = page.querySelector('.collectionItems');
- collectionItems.insertAdjacentHTML('beforeend', html);
- imageLoader.lazyChildren(collectionItems);
- }
-
- function renderMusicVideos(page, item, user) {
- connectionManager.getApiClient(item.ServerId).getItems(user.Id, {
- SortBy: 'SortName',
- SortOrder: 'Ascending',
- IncludeItemTypes: 'MusicVideo',
- Recursive: true,
- Fields: 'PrimaryImageAspectRatio,BasicSyncInfo,CanDelete,MediaSourceCount',
- AlbumIds: item.Id
- }).then(function (result) {
- if (result.Items.length) {
- page.querySelector('#musicVideosCollapsible').classList.remove('hide');
- const musicVideosContent = page.querySelector('.musicVideosContent');
- musicVideosContent.innerHTML = getVideosHtml(result.Items);
- imageLoader.lazyChildren(musicVideosContent);
- } else {
- page.querySelector('#musicVideosCollapsible').classList.add('hide');
- }
- });
- }
-
- function renderAdditionalParts(page, item, user) {
- connectionManager.getApiClient(item.ServerId).getAdditionalVideoParts(user.Id, item.Id).then(function (result) {
- if (result.Items.length) {
- page.querySelector('#additionalPartsCollapsible').classList.remove('hide');
- const additionalPartsContent = page.querySelector('#additionalPartsContent');
- additionalPartsContent.innerHTML = getVideosHtml(result.Items);
- imageLoader.lazyChildren(additionalPartsContent);
- } else {
- page.querySelector('#additionalPartsCollapsible').classList.add('hide');
- }
- });
- }
-
- function renderScenes(page, item) {
- let chapters = item.Chapters || [];
-
- if (chapters.length && !chapters[0].ImageTag && (chapters = []), chapters.length) {
- page.querySelector('#scenesCollapsible').classList.remove('hide');
- const scenesContent = page.querySelector('#scenesContent');
-
- import('chaptercardbuilder').then(({default: chaptercardbuilder}) => {
- chaptercardbuilder.buildChapterCards(item, chapters, {
- itemsContainer: scenesContent,
- backdropShape: 'overflowBackdrop',
- squareShape: 'overflowSquare',
- imageBlurhashes: item.ImageBlurHashes
- });
- });
+function renderSeriesSchedule(page, item) {
+ const apiClient = connectionManager.getApiClient(item.ServerId);
+ apiClient.getLiveTvPrograms({
+ UserId: apiClient.getCurrentUserId(),
+ HasAired: false,
+ SortBy: 'StartDate',
+ EnableTotalRecordCount: false,
+ EnableImages: false,
+ ImageTypeLimit: 0,
+ Limit: 50,
+ EnableUserData: false,
+ LibrarySeriesId: item.Id
+ }).then(function (result) {
+ if (result.Items.length) {
+ page.querySelector('#seriesScheduleSection').classList.remove('hide');
} else {
- page.querySelector('#scenesCollapsible').classList.add('hide');
+ page.querySelector('#seriesScheduleSection').classList.add('hide');
}
- }
- function getVideosHtml(items) {
- return cardBuilder.getCardsHtml({
- items: items,
- shape: 'autooverflow',
+ page.querySelector('#seriesScheduleList').innerHTML = listView.getListViewHtml({
+ items: result.Items,
+ enableUserDataButtons: false,
+ showParentTitle: false,
+ image: false,
+ showProgramDateTime: true,
+ mediaInfo: false,
showTitle: true,
- action: 'play',
- overlayText: false,
- centerText: true,
- showRuntime: true
+ moreButton: false,
+ action: 'programdialog'
});
+ loading.hide();
+ });
+}
+
+function inferContext(item) {
+ if (item.Type === 'Movie' || item.Type === 'BoxSet') {
+ return 'movies';
}
- function renderSpecials(page, item, user) {
- connectionManager.getApiClient(item.ServerId).getSpecialFeatures(user.Id, item.Id).then(function (specials) {
- const specialsContent = page.querySelector('#specialsContent');
- specialsContent.innerHTML = getVideosHtml(specials);
- imageLoader.lazyChildren(specialsContent);
- });
+ if (item.Type === 'Series' || item.Type === 'Season' || item.Type === 'Episode') {
+ return 'tvshows';
}
- function renderCast(page, item) {
- const people = (item.People || []).filter(function (p) {
- return p.Type === 'Actor';
- });
+ if (item.Type === 'MusicArtist' || item.Type === 'MusicAlbum' || item.Type === 'Audio' || item.Type === 'AudioBook') {
+ return 'music';
+ }
- if (!people.length) {
- return void page.querySelector('#castCollapsible').classList.add('hide');
+ if (item.Type === 'Program') {
+ return 'livetv';
+ }
+
+ return null;
+}
+
+function filterItemsByCollectionItemType(items, typeInfo) {
+ return items.filter(function (item) {
+ if (typeInfo.mediaType) {
+ return item.MediaType == typeInfo.mediaType;
}
- page.querySelector('#castCollapsible').classList.remove('hide');
- const castContent = page.querySelector('#castContent');
+ return item.Type == typeInfo.type;
+ });
+}
- import('peoplecardbuilder').then(({default: peoplecardbuilder}) => {
- peoplecardbuilder.buildPeopleCards(people, {
- itemsContainer: castContent,
- coverImage: true,
- serverId: item.ServerId,
- shape: 'overflowPortrait',
+function canPlaySomeItemInCollection(items) {
+ let i = 0;
+
+ for (let length = items.length; i < length; i++) {
+ if (playbackManager.canPlay(items[i])) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+function renderCollectionItems(page, parentItem, types, items) {
+ page.querySelector('.collectionItems').classList.remove('hide');
+ page.querySelector('.collectionItems').innerHTML = '';
+
+ for (const type of types) {
+ const typeItems = filterItemsByCollectionItemType(items, type);
+
+ if (typeItems.length) {
+ renderCollectionItemType(page, parentItem, type, typeItems);
+ }
+ }
+
+ const otherType = {
+ name: globalize.translate('HeaderOtherItems')
+ };
+ const otherTypeItems = items.filter(function (curr) {
+ return !types.filter(function (t) {
+ return filterItemsByCollectionItemType([curr], t).length > 0;
+ }).length;
+ });
+
+ if (otherTypeItems.length) {
+ renderCollectionItemType(page, parentItem, otherType, otherTypeItems);
+ }
+
+ if (!items.length) {
+ renderCollectionItemType(page, parentItem, {
+ name: globalize.translate('Items')
+ }, items);
+ }
+
+ const containers = page.querySelectorAll('.collectionItemsContainer');
+
+ const notifyRefreshNeeded = function () {
+ renderChildren(page, parentItem);
+ };
+
+ for (const container of containers) {
+ container.notifyRefreshNeeded = notifyRefreshNeeded;
+ }
+
+ // if nothing in the collection can be played hide play and shuffle buttons
+ if (!canPlaySomeItemInCollection(items)) {
+ hideAll(page, 'btnPlay', false);
+ hideAll(page, 'btnShuffle', false);
+ }
+
+ // HACK: Call autoFocuser again because btnPlay may be hidden, but focused by reloadFromItem
+ // FIXME: Sometimes focus does not move until all (?) sections are loaded
+ import('autoFocuser').then(({ default: autoFocuser }) => {
+ autoFocuser.autoFocus(page);
+ });
+}
+
+function renderCollectionItemType(page, parentItem, type, items) {
+ let html = '';
+ html += '';
+ html += '
';
+ html += '
';
+ html += '' + type.name + '';
+ html += '
';
+ html += '';
+ html += '
';
+ const shape = type.type == 'MusicAlbum' ? getSquareShape(false) : getPortraitShape(false);
+ html += cardBuilder.getCardsHtml({
+ items: items,
+ shape: shape,
+ showTitle: true,
+ showYear: type.mediaType === 'Video' || type.type === 'Series',
+ centerText: true,
+ lazy: true,
+ showDetailsMenu: true,
+ overlayMoreButton: true,
+ showAddToCollection: false,
+ showRemoveFromCollection: true,
+ collectionId: parentItem.Id
+ });
+ html += '
';
+ html += '
';
+ const collectionItems = page.querySelector('.collectionItems');
+ collectionItems.insertAdjacentHTML('beforeend', html);
+ imageLoader.lazyChildren(collectionItems);
+}
+
+function renderMusicVideos(page, item, user) {
+ connectionManager.getApiClient(item.ServerId).getItems(user.Id, {
+ SortBy: 'SortName',
+ SortOrder: 'Ascending',
+ IncludeItemTypes: 'MusicVideo',
+ Recursive: true,
+ Fields: 'PrimaryImageAspectRatio,BasicSyncInfo,CanDelete,MediaSourceCount',
+ AlbumIds: item.Id
+ }).then(function (result) {
+ if (result.Items.length) {
+ page.querySelector('#musicVideosCollapsible').classList.remove('hide');
+ const musicVideosContent = page.querySelector('.musicVideosContent');
+ musicVideosContent.innerHTML = getVideosHtml(result.Items);
+ imageLoader.lazyChildren(musicVideosContent);
+ } else {
+ page.querySelector('#musicVideosCollapsible').classList.add('hide');
+ }
+ });
+}
+
+function renderAdditionalParts(page, item, user) {
+ connectionManager.getApiClient(item.ServerId).getAdditionalVideoParts(user.Id, item.Id).then(function (result) {
+ if (result.Items.length) {
+ page.querySelector('#additionalPartsCollapsible').classList.remove('hide');
+ const additionalPartsContent = page.querySelector('#additionalPartsContent');
+ additionalPartsContent.innerHTML = getVideosHtml(result.Items);
+ imageLoader.lazyChildren(additionalPartsContent);
+ } else {
+ page.querySelector('#additionalPartsCollapsible').classList.add('hide');
+ }
+ });
+}
+
+function renderScenes(page, item) {
+ let chapters = item.Chapters || [];
+
+ if (chapters.length && !chapters[0].ImageTag && (chapters = []), chapters.length) {
+ page.querySelector('#scenesCollapsible').classList.remove('hide');
+ const scenesContent = page.querySelector('#scenesContent');
+
+ import('chaptercardbuilder').then(({ default: chaptercardbuilder }) => {
+ chaptercardbuilder.buildChapterCards(item, chapters, {
+ itemsContainer: scenesContent,
+ backdropShape: 'overflowBackdrop',
+ squareShape: 'overflowSquare',
imageBlurhashes: item.ImageBlurHashes
});
});
+ } else {
+ page.querySelector('#scenesCollapsible').classList.add('hide');
+ }
+}
+
+function getVideosHtml(items) {
+ return cardBuilder.getCardsHtml({
+ items: items,
+ shape: 'autooverflow',
+ showTitle: true,
+ action: 'play',
+ overlayText: false,
+ centerText: true,
+ showRuntime: true
+ });
+}
+
+function renderSpecials(page, item, user) {
+ connectionManager.getApiClient(item.ServerId).getSpecialFeatures(user.Id, item.Id).then(function (specials) {
+ const specialsContent = page.querySelector('#specialsContent');
+ specialsContent.innerHTML = getVideosHtml(specials);
+ imageLoader.lazyChildren(specialsContent);
+ });
+}
+
+function renderCast(page, item) {
+ const people = (item.People || []).filter(function (p) {
+ return p.Type === 'Actor';
+ });
+
+ if (!people.length) {
+ return void page.querySelector('#castCollapsible').classList.add('hide');
}
- function itemDetailPage() {
- const self = this;
- self.setInitialCollapsibleState = setInitialCollapsibleState;
- self.renderDetails = renderDetails;
- self.renderCast = renderCast;
+ page.querySelector('#castCollapsible').classList.remove('hide');
+ const castContent = page.querySelector('#castContent');
+
+ import('peoplecardbuilder').then(({ default: peoplecardbuilder }) => {
+ peoplecardbuilder.buildPeopleCards(people, {
+ itemsContainer: castContent,
+ coverImage: true,
+ serverId: item.ServerId,
+ shape: 'overflowPortrait',
+ imageBlurhashes: item.ImageBlurHashes
+ });
+ });
+}
+
+function itemDetailPage() {
+ const self = this;
+ self.setInitialCollapsibleState = setInitialCollapsibleState;
+ self.renderDetails = renderDetails;
+ self.renderCast = renderCast;
+}
+
+function bindAll(view, selector, eventName, fn) {
+ const elems = view.querySelectorAll(selector);
+
+ for (const elem of elems) {
+ elem.addEventListener(eventName, fn);
}
+}
- function bindAll(view, selector, eventName, fn) {
- const elems = view.querySelectorAll(selector);
+function onTrackSelectionsSubmit(e) {
+ e.preventDefault();
+ return false;
+}
- for (const elem of elems) {
- elem.addEventListener(eventName, fn);
- }
- }
+window.ItemDetailPage = new itemDetailPage();
- function onTrackSelectionsSubmit(e) {
- e.preventDefault();
- return false;
- }
+export default function (view, params) {
+ function reload(instance, page, params) {
+ loading.show();
- window.ItemDetailPage = new itemDetailPage();
-
- export default function (view, params) {
- function reload(instance, page, params) {
- loading.show();
-
- const apiClient = params.serverId ? connectionManager.getApiClient(params.serverId) : ApiClient;
-
- Promise.all([getPromise(apiClient, params), apiClient.getCurrentUser()]).then(([item, user]) => {
- currentItem = item;
- reloadFromItem(instance, page, params, item, user);
- }).catch((error) => {
- console.error('failed to get item or current user: ', error);
- });
- }
-
- function splitVersions(instance, page, apiClient, params) {
- import('confirm').then(({default: confirm}) => {
- confirm('Are you sure you wish to split the media sources into separate items?', 'Split Media Apart').then(function () {
- loading.show();
- apiClient.ajax({
- type: 'DELETE',
- url: apiClient.getUrl('Videos/' + params.id + '/AlternateSources')
- }).then(function () {
- loading.hide();
- reload(instance, page, params);
- });
- });
- });
- }
-
- function getPlayOptions(startPosition) {
- const audioStreamIndex = view.querySelector('.selectAudio').value || null;
- return {
- startPositionTicks: startPosition,
- mediaSourceId: view.querySelector('.selectSource').value,
- audioStreamIndex: audioStreamIndex,
- subtitleStreamIndex: view.querySelector('.selectSubtitles').value
- };
- }
-
- function playItem(item, startPosition) {
- const playOptions = getPlayOptions(startPosition);
- playOptions.items = [item];
- playbackManager.play(playOptions);
- }
-
- function playTrailer() {
- playbackManager.playTrailers(currentItem);
- }
-
- function playCurrentItem(button, mode) {
- const item = currentItem;
-
- if (item.Type === 'Program') {
- const apiClient = connectionManager.getApiClient(item.ServerId);
- return void apiClient.getLiveTvChannel(item.ChannelId, apiClient.getCurrentUserId()).then(function (channel) {
- playbackManager.play({
- items: [channel]
- });
- });
- }
-
- playItem(item, item.UserData && mode === 'resume' ? item.UserData.PlaybackPositionTicks : 0);
- }
-
- function onPlayClick() {
- playCurrentItem(this, this.getAttribute('data-mode'));
- }
-
- function onPosterClick(e) {
- itemShortcuts.onClick.call(view.querySelector('.detailImageContainer'), e);
- }
-
- function onInstantMixClick() {
- playbackManager.instantMix(currentItem);
- }
-
- function onShuffleClick() {
- playbackManager.shuffle(currentItem);
- }
-
- function onCancelSeriesTimerClick() {
- import('recordingHelper').then(({default: recordingHelper}) => {
- recordingHelper.cancelSeriesTimerWithConfirmation(currentItem.Id, currentItem.ServerId).then(function () {
- Dashboard.navigate('livetv.html');
- });
- });
- }
-
- function onCancelTimerClick() {
- import('recordingHelper').then(({default: recordingHelper}) => {
- recordingHelper.cancelTimer(connectionManager.getApiClient(currentItem.ServerId), currentItem.TimerId).then(function () {
- reload(self, view, params);
- });
- });
- }
-
- function onPlayTrailerClick() {
- playTrailer();
- }
-
- function onDownloadClick() {
- import('fileDownloader').then(({default: fileDownloader}) => {
- const downloadHref = apiClient.getItemDownloadUrl(currentItem.Id);
- fileDownloader.download([{
- url: downloadHref,
- itemId: currentItem.Id,
- serverId: currentItem.serverId
- }]);
- });
- }
-
- function onMoreCommandsClick() {
- var button = this;
- var selectedItem = currentItem;
- apiClient.getItem(apiClient.getCurrentUserId(), view.querySelector('.selectSource').value).then(function (item) {
- selectedItem = item;
-
- apiClient.getCurrentUser().then(function (user) {
- itemContextMenu.show(getContextMenuOptions(selectedItem, user, button)).then(function (result) {
- if (result.deleted) {
- appRouter.goHome();
- } else if (result.updated) {
- reload(self, view, params);
- }
- });
- });
- });
- }
-
- function onPlayerChange() {
- renderTrackSelections(view, self, currentItem);
- setTrailerButtonVisibility(view, currentItem);
- }
-
- function onWebSocketMessage(e, data) {
- const msg = data;
-
- if (msg.MessageType === 'UserDataChanged' && currentItem && msg.Data.UserId == apiClient.getCurrentUserId()) {
- const key = currentItem.UserData.Key;
- const userData = msg.Data.UserDataList.filter(function (u) {
- return u.Key == key;
- })[0];
-
- if (userData) {
- currentItem.UserData = userData;
- reloadPlayButtons(view, currentItem);
- refreshImage(view, currentItem);
- }
- }
- }
-
- let currentItem;
- const self = this;
const apiClient = params.serverId ? connectionManager.getApiClient(params.serverId) : ApiClient;
- view.querySelectorAll('.btnPlay');
- bindAll(view, '.btnPlay', 'click', onPlayClick);
- bindAll(view, '.btnResume', 'click', onPlayClick);
- bindAll(view, '.btnInstantMix', 'click', onInstantMixClick);
- bindAll(view, '.btnShuffle', 'click', onShuffleClick);
- bindAll(view, '.btnPlayTrailer', 'click', onPlayTrailerClick);
- bindAll(view, '.btnCancelSeriesTimer', 'click', onCancelSeriesTimerClick);
- bindAll(view, '.btnCancelTimer', 'click', onCancelTimerClick);
- bindAll(view, '.btnDownload', 'click', onDownloadClick);
- view.querySelector('.detailImageContainer').addEventListener('click', onPosterClick);
- view.querySelector('.trackSelections').addEventListener('submit', onTrackSelectionsSubmit);
- view.querySelector('.btnSplitVersions').addEventListener('click', function () {
- splitVersions(self, view, apiClient, params);
- });
- bindAll(view, '.btnMoreCommands', 'click', onMoreCommandsClick);
- view.querySelector('.selectSource').addEventListener('change', function () {
- renderVideoSelections(view, self._currentPlaybackMediaSources);
- renderAudioSelections(view, self._currentPlaybackMediaSources);
- renderSubtitleSelections(view, self._currentPlaybackMediaSources);
- });
- view.addEventListener('viewshow', function (e) {
- const page = this;
- libraryMenu.setTransparentMenu(true);
-
- if (e.detail.isRestored) {
- if (currentItem) {
- Emby.Page.setTitle('');
- renderTrackSelections(page, self, currentItem, true);
- }
- } else {
- reload(self, page, params);
- }
-
- events.on(apiClient, 'message', onWebSocketMessage);
- events.on(playbackManager, 'playerchange', onPlayerChange);
- });
- view.addEventListener('viewbeforehide', function () {
- events.off(apiClient, 'message', onWebSocketMessage);
- events.off(playbackManager, 'playerchange', onPlayerChange);
- libraryMenu.setTransparentMenu(false);
- });
- view.addEventListener('viewdestroy', function () {
- currentItem = null;
- self._currentPlaybackMediaSources = null;
- self.currentRecordingFields = null;
+ Promise.all([getPromise(apiClient, params), apiClient.getCurrentUser()]).then(([item, user]) => {
+ currentItem = item;
+ reloadFromItem(instance, page, params, item, user);
+ }).catch((error) => {
+ console.error('failed to get item or current user: ', error);
});
}
-/* eslint-enable indent */
+ function splitVersions(instance, page, apiClient, params) {
+ import('confirm').then(({ default: confirm }) => {
+ confirm('Are you sure you wish to split the media sources into separate items?', 'Split Media Apart').then(function () {
+ loading.show();
+ apiClient.ajax({
+ type: 'DELETE',
+ url: apiClient.getUrl('Videos/' + params.id + '/AlternateSources')
+ }).then(function () {
+ loading.hide();
+ reload(instance, page, params);
+ });
+ });
+ });
+ }
+
+ function getPlayOptions(startPosition) {
+ const audioStreamIndex = view.querySelector('.selectAudio').value || null;
+ return {
+ startPositionTicks: startPosition,
+ mediaSourceId: view.querySelector('.selectSource').value,
+ audioStreamIndex: audioStreamIndex,
+ subtitleStreamIndex: view.querySelector('.selectSubtitles').value
+ };
+ }
+
+ function playItem(item, startPosition) {
+ const playOptions = getPlayOptions(startPosition);
+ playOptions.items = [item];
+ playbackManager.play(playOptions);
+ }
+
+ function playTrailer() {
+ playbackManager.playTrailers(currentItem);
+ }
+
+ function playCurrentItem(button, mode) {
+ const item = currentItem;
+
+ if (item.Type === 'Program') {
+ const apiClient = connectionManager.getApiClient(item.ServerId);
+ return void apiClient.getLiveTvChannel(item.ChannelId, apiClient.getCurrentUserId()).then(function (channel) {
+ playbackManager.play({
+ items: [channel]
+ });
+ });
+ }
+
+ playItem(item, item.UserData && mode === 'resume' ? item.UserData.PlaybackPositionTicks : 0);
+ }
+
+ function onPlayClick() {
+ playCurrentItem(this, this.getAttribute('data-mode'));
+ }
+
+ function onPosterClick(e) {
+ itemShortcuts.onClick.call(view.querySelector('.detailImageContainer'), e);
+ }
+
+ function onInstantMixClick() {
+ playbackManager.instantMix(currentItem);
+ }
+
+ function onShuffleClick() {
+ playbackManager.shuffle(currentItem);
+ }
+
+ function onCancelSeriesTimerClick() {
+ import('recordingHelper').then(({ default: recordingHelper }) => {
+ recordingHelper.cancelSeriesTimerWithConfirmation(currentItem.Id, currentItem.ServerId).then(function () {
+ Dashboard.navigate('livetv.html');
+ });
+ });
+ }
+
+ function onCancelTimerClick() {
+ import('recordingHelper').then(({ default: recordingHelper }) => {
+ recordingHelper.cancelTimer(connectionManager.getApiClient(currentItem.ServerId), currentItem.TimerId).then(function () {
+ reload(self, view, params);
+ });
+ });
+ }
+
+ function onPlayTrailerClick() {
+ playTrailer();
+ }
+
+ function onDownloadClick() {
+ import('fileDownloader').then(({ default: fileDownloader }) => {
+ const downloadHref = apiClient.getItemDownloadUrl(currentItem.Id);
+ fileDownloader.download([{
+ url: downloadHref,
+ itemId: currentItem.Id,
+ serverId: currentItem.serverId
+ }]);
+ });
+ }
+
+ function onMoreCommandsClick() {
+ const button = this;
+ let selectedItem = view.querySelector('.selectSource').value || currentItem.Id;
+
+ apiClient.getItem(apiClient.getCurrentUserId(), selectedItem).then(function (item) {
+ selectedItem = item;
+
+ apiClient.getCurrentUser().then(function (user) {
+ itemContextMenu.show(getContextMenuOptions(selectedItem, user, button)).then(function (result) {
+ if (result.deleted) {
+ appRouter.goHome();
+ } else if (result.updated) {
+ reload(self, view, params);
+ }
+ });
+ });
+ });
+ }
+
+ function onPlayerChange() {
+ renderTrackSelections(view, self, currentItem);
+ setTrailerButtonVisibility(view, currentItem);
+ }
+
+ function onWebSocketMessage(e, data) {
+ const msg = data;
+
+ if (msg.MessageType === 'UserDataChanged' && currentItem && msg.Data.UserId == apiClient.getCurrentUserId()) {
+ const key = currentItem.UserData.Key;
+ const userData = msg.Data.UserDataList.filter(function (u) {
+ return u.Key == key;
+ })[0];
+
+ if (userData) {
+ currentItem.UserData = userData;
+ reloadPlayButtons(view, currentItem);
+ refreshImage(view, currentItem);
+ }
+ }
+ }
+
+ let currentItem;
+ const self = this;
+ const apiClient = params.serverId ? connectionManager.getApiClient(params.serverId) : ApiClient;
+ view.querySelectorAll('.btnPlay');
+ bindAll(view, '.btnPlay', 'click', onPlayClick);
+ bindAll(view, '.btnResume', 'click', onPlayClick);
+ bindAll(view, '.btnInstantMix', 'click', onInstantMixClick);
+ bindAll(view, '.btnShuffle', 'click', onShuffleClick);
+ bindAll(view, '.btnPlayTrailer', 'click', onPlayTrailerClick);
+ bindAll(view, '.btnCancelSeriesTimer', 'click', onCancelSeriesTimerClick);
+ bindAll(view, '.btnCancelTimer', 'click', onCancelTimerClick);
+ bindAll(view, '.btnDownload', 'click', onDownloadClick);
+ view.querySelector('.detailImageContainer').addEventListener('click', onPosterClick);
+ view.querySelector('.trackSelections').addEventListener('submit', onTrackSelectionsSubmit);
+ view.querySelector('.btnSplitVersions').addEventListener('click', function () {
+ splitVersions(self, view, apiClient, params);
+ });
+ bindAll(view, '.btnMoreCommands', 'click', onMoreCommandsClick);
+ view.querySelector('.selectSource').addEventListener('change', function () {
+ renderVideoSelections(view, self._currentPlaybackMediaSources);
+ renderAudioSelections(view, self._currentPlaybackMediaSources);
+ renderSubtitleSelections(view, self._currentPlaybackMediaSources);
+ });
+ view.addEventListener('viewshow', function (e) {
+ const page = this;
+
+ libraryMenu.setTransparentMenu(true);
+
+ if (e.detail.isRestored) {
+ if (currentItem) {
+ Emby.Page.setTitle('');
+ renderTrackSelections(page, self, currentItem, true);
+ }
+ } else {
+ reload(self, page, params);
+ }
+
+ events.on(apiClient, 'message', onWebSocketMessage);
+ events.on(playbackManager, 'playerchange', onPlayerChange);
+ });
+ view.addEventListener('viewbeforehide', function () {
+ events.off(apiClient, 'message', onWebSocketMessage);
+ events.off(playbackManager, 'playerchange', onPlayerChange);
+ libraryMenu.setTransparentMenu(false);
+ });
+ view.addEventListener('viewdestroy', function () {
+ currentItem = null;
+ self._currentPlaybackMediaSources = null;
+ self.currentRecordingFields = null;
+ });
+}
diff --git a/src/controllers/playback/video/index.js b/src/controllers/playback/video/index.js
index 420268ea75..a6e17a8063 100644
--- a/src/controllers/playback/video/index.js
+++ b/src/controllers/playback/video/index.js
@@ -693,7 +693,7 @@ import 'css!assets/css/videoosd';
lastUpdateTime = now;
const player = this;
currentRuntimeTicks = playbackManager.duration(player);
- const currentTime = playbackManager.currentTime(player);
+ const currentTime = playbackManager.currentTime(player) * 10000;
updateTimeDisplay(currentTime, currentRuntimeTicks, playbackManager.playbackStartTime(player), playbackManager.getBufferedRanges(player));
const item = currentItem;
refreshProgramInfoIfNeeded(player, item);
diff --git a/src/legacy/vendorStyles.js b/src/legacy/vendorStyles.js
new file mode 100644
index 0000000000..74a90ba04d
--- /dev/null
+++ b/src/legacy/vendorStyles.js
@@ -0,0 +1,34 @@
+// Polyfill for vendor prefixed style properties
+
+(function () {
+ const vendorProperties = {
+ 'transform': ['webkitTransform'],
+ 'transition': ['webkitTransition']
+ };
+
+ const elem = document.createElement('div');
+
+ function polyfillProperty(name) {
+ if (!(name in elem.style)) {
+ (vendorProperties[name] || []).every((vendorName) => {
+ if (vendorName in elem.style) {
+ console.debug(`polyfill '${name}' with '${vendorName}'`);
+
+ Object.defineProperty(CSSStyleDeclaration.prototype, name, {
+ get: function () { return this[vendorName]; },
+ set: function (val) { this[vendorName] = val; }
+ });
+
+ return false;
+ }
+
+ return true;
+ });
+ }
+ }
+
+ if (elem.style instanceof CSSStyleDeclaration) {
+ polyfillProperty('transform');
+ polyfillProperty('transition');
+ }
+})();
diff --git a/src/plugins/chromecastPlayer/plugin.js b/src/plugins/chromecastPlayer/plugin.js
index b7e6d05969..31d9568898 100644
--- a/src/plugins/chromecastPlayer/plugin.js
+++ b/src/plugins/chromecastPlayer/plugin.js
@@ -931,9 +931,9 @@ class ChromecastPlayer {
return state.VolumeLevel == null ? 100 : state.VolumeLevel;
}
- isPlaying() {
+ isPlaying(mediaType) {
const state = this.lastPlayerData || {};
- return state.NowPlayingItem != null;
+ return state.NowPlayingItem != null && (state.NowPlayingItem.MediaType === mediaType || !mediaType);
}
isPlayingVideo() {
@@ -950,12 +950,12 @@ class ChromecastPlayer {
currentTime(val) {
if (val != null) {
- return this.seek(val);
+ return this.seek(val * 10000);
}
let state = this.lastPlayerData || {};
state = state.PlayState || {};
- return state.PositionTicks;
+ return state.PositionTicks / 10000;
}
duration() {
diff --git a/src/plugins/htmlAudioPlayer/plugin.js b/src/plugins/htmlAudioPlayer/plugin.js
index acce15df88..6f413fac50 100644
--- a/src/plugins/htmlAudioPlayer/plugin.js
+++ b/src/plugins/htmlAudioPlayer/plugin.js
@@ -132,10 +132,7 @@ class HtmlAudioPlayer {
return new Promise(function (resolve, reject) {
requireHlsPlayer(function () {
const hls = new Hls({
- manifestLoadingTimeOut: 20000,
- xhrSetup: function (xhr, url) {
- xhr.withCredentials = true;
- }
+ manifestLoadingTimeOut: 20000
});
hls.loadSource(val);
hls.attachMedia(elem);
diff --git a/src/plugins/htmlVideoPlayer/plugin.js b/src/plugins/htmlVideoPlayer/plugin.js
index 58c8624e34..88329fecff 100644
--- a/src/plugins/htmlVideoPlayer/plugin.js
+++ b/src/plugins/htmlVideoPlayer/plugin.js
@@ -393,10 +393,7 @@ function tryRemoveElement(elem) {
return new Promise((resolve, reject) => {
requireHlsPlayer(() => {
const hls = new Hls({
- manifestLoadingTimeOut: 20000,
- xhrSetup(xhr) {
- xhr.withCredentials = true;
- }
+ manifestLoadingTimeOut: 20000
});
hls.loadSource(url);
hls.attachMedia(elem);
diff --git a/src/plugins/sessionPlayer/plugin.js b/src/plugins/sessionPlayer/plugin.js
index cbeb6f34b4..6ae5c1c712 100644
--- a/src/plugins/sessionPlayer/plugin.js
+++ b/src/plugins/sessionPlayer/plugin.js
@@ -322,12 +322,12 @@ class SessionPlayer {
currentTime(val) {
if (val != null) {
- return this.seek(val);
+ return this.seek(val * 10000);
}
let state = this.lastPlayerData || {};
state = state.PlayState || {};
- return state.PositionTicks;
+ return state.PositionTicks / 10000;
}
duration() {
@@ -466,9 +466,9 @@ class SessionPlayer {
sendCommandByName(this, 'DisplayContent', options);
}
- isPlaying() {
+ isPlaying(mediaType) {
const state = this.lastPlayerData || {};
- return state.NowPlayingItem != null;
+ return state.NowPlayingItem != null && (state.NowPlayingItem.MediaType === mediaType || !mediaType);
}
isPlayingVideo() {
diff --git a/src/scripts/apploader.js b/src/scripts/apploader.js
index f5f6850c40..fdf52fd699 100644
--- a/src/scripts/apploader.js
+++ b/src/scripts/apploader.js
@@ -35,7 +35,8 @@
// Promise() being missing on some legacy browser, and a funky one
// is Promise() present but buggy on WebOS 2
window.Promise = undefined;
- window.Promise = undefined;
+ /* eslint-disable-next-line no-restricted-globals -- Explicit check on self needed */
+ self.Promise = undefined;
}
if (!window.Promise) {
diff --git a/src/scripts/site.js b/src/scripts/site.js
index 9ba7e904a1..b6bd7b4793 100644
--- a/src/scripts/site.js
+++ b/src/scripts/site.js
@@ -222,6 +222,7 @@ function initClient() {
});
require(['mouseManager']);
require(['focusPreventScroll']);
+ require(['vendorStyles']);
require(['autoFocuser'], function(autoFocuser) {
autoFocuser.enable();
});
@@ -656,6 +657,7 @@ function initClient() {
});
define('slideshow', [componentsPath + '/slideshow/slideshow'], returnFirstDependency);
define('focusPreventScroll', ['legacy/focusPreventScroll'], returnFirstDependency);
+ define('vendorStyles', ['legacy/vendorStyles'], returnFirstDependency);
define('userdataButtons', [componentsPath + '/userdatabuttons/userdatabuttons'], returnFirstDependency);
define('listView', [componentsPath + '/listview/listview'], returnFirstDependency);
define('indicators', [componentsPath + '/indicators/indicators'], returnFirstDependency);
diff --git a/yarn.lock b/yarn.lock
index 2175f0197c..4f8dd29c45 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3218,10 +3218,10 @@ dashdash@^1.12.0:
dependencies:
assert-plus "^1.0.0"
-date-fns@^2.15.0:
- version "2.15.0"
- resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.15.0.tgz#424de6b3778e4e69d3ff27046ec136af58ae5d5f"
- integrity sha512-ZCPzAMJZn3rNUvvQIMlXhDr4A+Ar07eLeGsGREoWU19a3Pqf5oYa+ccd+B3F6XVtQY6HANMFdOQ8A+ipFnvJdQ==
+date-fns@^2.16.0:
+ version "2.16.0"
+ resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.16.0.tgz#d34f0f5f2fd498c984513042e8f7247ea86c4cb7"
+ integrity sha512-DWTRyfOA85sZ4IiXPHhiRIOs3fW5U6Msrp+gElXARa6EpoQTXPyHQmh7hr+ssw2nx9FtOQWnAMJKgL5vaJqILw==
dateformat@^2.0.0:
version "2.2.0"
@@ -3499,12 +3499,12 @@ dom-serializer@0:
domelementtype "^2.0.1"
entities "^2.0.0"
-dom7@^2.1.5:
- version "2.1.5"
- resolved "https://registry.yarnpkg.com/dom7/-/dom7-2.1.5.tgz#a79411017800b31d8400070cdaebbfc92c1f6377"
- integrity sha512-xnhwVgyOh3eD++/XGtH+5qBwYTgCm0aW91GFgPJ3XG+jlsRLyJivnbP0QmUBFhI+Oaz9FV0s7cxgXHezwOEBYA==
+dom7@^3.0.0-alpha.7:
+ version "3.0.0-alpha.7"
+ resolved "https://registry.yarnpkg.com/dom7/-/dom7-3.0.0-alpha.7.tgz#3b4ba156a83fa37fb3fa34b8ab40a1a41a56feb1"
+ integrity sha512-3epkQPsKsbk2Dixqqgm2DT/KzhiAPByjDK7emu6owwFLbM5UoiqWKgdsH+6PpMEgoeR6Ex/bW1UbOe0FWZU0zg==
dependencies:
- ssr-window "^2.0.0"
+ ssr-window "^3.0.0-alpha.1"
domain-browser@^1.1.1:
version "1.2.0"
@@ -10400,10 +10400,10 @@ sshpk@^1.7.0:
safer-buffer "^2.0.2"
tweetnacl "~0.14.0"
-ssr-window@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/ssr-window/-/ssr-window-2.0.0.tgz#98c301aef99523317f8d69618f0010791096efc4"
- integrity sha512-NXzN+/HPObKAx191H3zKlYomE5WrVIkoCB5IaSdvKokxTpjBdWfr0RaP+1Z5KOfDT0ZVz+2tdtiBkhsEQ9p+0A==
+ssr-window@^3.0.0-alpha.1, ssr-window@^3.0.0-alpha.4:
+ version "3.0.0-alpha.4"
+ resolved "https://registry.yarnpkg.com/ssr-window/-/ssr-window-3.0.0-alpha.4.tgz#0c69a18c4305ecccdd8e11596155ca07b635f345"
+ integrity sha512-+dBRP/pZ+VyITxTzD0lMDzDwN/BmfUl8xi2e6t5Nz4+FqUphfcBLB1OOUSYCRNFB25rD3c8AJRYpY5rHTbL+kg==
ssri@^6.0.1:
version "6.0.1"
@@ -10923,7 +10923,7 @@ supports-color@^3.2.3:
dependencies:
has-flag "^1.0.0"
-supports-color@^5.3.0, supports-color@^5.5.0:
+supports-color@^5.3.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
@@ -10976,13 +10976,13 @@ svgo@^1.0.0, svgo@^1.3.2:
unquote "~1.1.1"
util.promisify "~1.0.0"
-swiper@^5.4.5:
- version "5.4.5"
- resolved "https://registry.yarnpkg.com/swiper/-/swiper-5.4.5.tgz#a350f654bf68426dbb651793824925512d223c0f"
- integrity sha512-7QjA0XpdOmiMoClfaZ2lYN6ICHcMm72LXiY+NF4fQLFidigameaofvpjEEiTQuw3xm5eksG5hzkaRsjQX57vtA==
+swiper@^6.1.1:
+ version "6.1.1"
+ resolved "https://registry.yarnpkg.com/swiper/-/swiper-6.1.1.tgz#1246f28557dd33968dc43e926bc6e9e9a7b3850d"
+ integrity sha512-w6rmEUnpuSWvzuIDJ+nTi7YQ4+pvr++zUnBO2VxkzOZbzQzcMNKNw1yj0RFEok682IHDPCs3LXSl8zSQ+zDEdw==
dependencies:
- dom7 "^2.1.5"
- ssr-window "^2.0.0"
+ dom7 "^3.0.0-alpha.7"
+ ssr-window "^3.0.0-alpha.4"
symbol-observable@1.0.1:
version "1.0.1"
@@ -11944,17 +11944,17 @@ webpack-sources@^1.4.0, webpack-sources@^1.4.1:
source-list-map "^2.0.0"
source-map "~0.6.1"
-webpack-stream@^5.2.1:
- version "5.2.1"
- resolved "https://registry.yarnpkg.com/webpack-stream/-/webpack-stream-5.2.1.tgz#35c992161399fe8cad9c10d4a5c258f022629b39"
- integrity sha512-WvyVU0K1/VB1NZ7JfsaemVdG0PXAQUqbjUNW4A58th4pULvKMQxG+y33HXTL02JvD56ko2Cub+E2NyPwrLBT/A==
+webpack-stream@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/webpack-stream/-/webpack-stream-6.0.0.tgz#0524b739a3c3a487362ee2e97522d0b8d366a510"
+ integrity sha512-bYv7apmGB1j0JBpa5Fgyky/1mWyzHOnUPXv+RmkgpK4FXPWCMBspgnYFmhE7Ly68JSp77eonFzm6WArWy4afpQ==
dependencies:
fancy-log "^1.3.3"
lodash.clone "^4.3.2"
lodash.some "^4.2.2"
- memory-fs "^0.4.1"
+ memory-fs "^0.5.0"
plugin-error "^1.0.1"
- supports-color "^5.5.0"
+ supports-color "^7.1.0"
through "^2.3.8"
vinyl "^2.1.0"
webpack "^4.26.1"