2021-07-10 11:45:40 +02:00
|
|
|
import { intervalToDuration } from 'date-fns';
|
2020-08-16 20:24:45 +02:00
|
|
|
import { appHost } from '../../components/apphost';
|
2020-08-14 08:46:34 +02:00
|
|
|
import loading from '../../components/loading/loading';
|
2020-08-16 20:24:45 +02:00
|
|
|
import { appRouter } from '../../components/appRouter';
|
2020-08-14 08:46:34 +02:00
|
|
|
import layoutManager from '../../components/layoutManager';
|
2020-10-17 19:08:56 +01:00
|
|
|
import { Events } from 'jellyfin-apiclient';
|
2020-08-14 08:46:34 +02:00
|
|
|
import * as userSettings from '../../scripts/settings/userSettings';
|
|
|
|
import cardBuilder from '../../components/cardbuilder/cardBuilder';
|
|
|
|
import datetime from '../../scripts/datetime';
|
|
|
|
import mediaInfo from '../../components/mediainfo/mediainfo';
|
|
|
|
import backdrop from '../../components/backdrop/backdrop';
|
|
|
|
import listView from '../../components/listview/listview';
|
|
|
|
import itemContextMenu from '../../components/itemContextMenu';
|
|
|
|
import itemHelper from '../../components/itemHelper';
|
|
|
|
import dom from '../../scripts/dom';
|
|
|
|
import imageLoader from '../../components/images/imageLoader';
|
|
|
|
import libraryMenu from '../../scripts/libraryMenu';
|
|
|
|
import globalize from '../../scripts/globalize';
|
|
|
|
import browser from '../../scripts/browser';
|
2020-08-16 20:24:45 +02:00
|
|
|
import { playbackManager } from '../../components/playback/playbackmanager';
|
2021-01-26 15:31:58 -05:00
|
|
|
import '../../assets/css/scrollstyles.scss';
|
2020-08-14 08:46:34 +02:00
|
|
|
import '../../elements/emby-itemscontainer/emby-itemscontainer';
|
|
|
|
import '../../elements/emby-checkbox/emby-checkbox';
|
|
|
|
import '../../elements/emby-button/emby-button';
|
|
|
|
import '../../elements/emby-playstatebutton/emby-playstatebutton';
|
|
|
|
import '../../elements/emby-ratingbutton/emby-ratingbutton';
|
|
|
|
import '../../elements/emby-scroller/emby-scroller';
|
|
|
|
import '../../elements/emby-select/emby-select';
|
|
|
|
import itemShortcuts from '../../components/shortcuts';
|
2020-10-12 23:08:55 +01:00
|
|
|
import Dashboard from '../../scripts/clientUtils';
|
2020-10-17 19:08:56 +01:00
|
|
|
import ServerConnections from '../../components/ServerConnections';
|
2020-10-18 15:18:15 +01:00
|
|
|
import confirm from '../../components/confirm/confirm';
|
2020-11-08 19:44:19 +00:00
|
|
|
import { download } from '../../scripts/fileDownloader';
|
2020-07-29 10:05:26 +01:00
|
|
|
|
2022-01-15 20:03:13 +03:00
|
|
|
function autoFocus(container) {
|
|
|
|
import('../../components/autoFocuser').then(({ default: autoFocuser }) => {
|
|
|
|
autoFocuser.autoFocus(container);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function getPromise(apiClient, params) {
|
|
|
|
const id = params.id;
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (id) {
|
|
|
|
return apiClient.getItem(apiClient.getCurrentUserId(), id);
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (params.seriesTimerId) {
|
|
|
|
return apiClient.getLiveTvSeriesTimer(params.seriesTimerId);
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (params.genre) {
|
|
|
|
return apiClient.getGenre(params.genre, apiClient.getCurrentUserId());
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (params.musicgenre) {
|
|
|
|
return apiClient.getMusicGenre(params.musicgenre, apiClient.getCurrentUserId());
|
|
|
|
}
|
2020-06-17 15:45:23 +02:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (params.musicartist) {
|
|
|
|
return apiClient.getArtist(params.musicartist, apiClient.getCurrentUserId());
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
throw new Error('Invalid request');
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
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 getProgramScheduleHtml(items) {
|
|
|
|
let html = '';
|
|
|
|
|
|
|
|
html += '<div is="emby-itemscontainer" class="itemsContainer vertical-list" data-contextmenu="false">';
|
|
|
|
html += listView.getListViewHtml({
|
|
|
|
items: items,
|
|
|
|
enableUserDataButtons: false,
|
|
|
|
image: true,
|
|
|
|
imageSource: 'channel',
|
|
|
|
showProgramDateTime: true,
|
|
|
|
showChannel: false,
|
|
|
|
mediaInfo: false,
|
|
|
|
action: 'none',
|
|
|
|
moreButton: false,
|
|
|
|
recordButton: false
|
|
|
|
});
|
|
|
|
|
|
|
|
html += '</div>';
|
|
|
|
|
|
|
|
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');
|
|
|
|
}
|
|
|
|
|
|
|
|
hideAll(page, 'btnCancelTimer', true);
|
|
|
|
}
|
|
|
|
|
|
|
|
function renderSeriesTimerEditor(page, item, apiClient, user) {
|
|
|
|
if (item.Type !== 'SeriesTimer') {
|
|
|
|
return void hideAll(page, 'btnCancelSeriesTimer');
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (user.Policy.EnableLiveTvManagement) {
|
2020-08-14 08:46:34 +02:00
|
|
|
import('../../components/recordingcreator/seriesrecordingeditor').then(({ default: seriesRecordingEditor }) => {
|
2020-08-25 15:44:01 +01:00
|
|
|
seriesRecordingEditor.embed(item, apiClient.serverId(), {
|
|
|
|
context: page.querySelector('.seriesRecordingEditor')
|
|
|
|
});
|
|
|
|
});
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
page.querySelector('.seriesTimerScheduleSection').classList.remove('hide');
|
|
|
|
hideAll(page, 'btnCancelSeriesTimer', true);
|
|
|
|
return void renderSeriesTimerSchedule(page, apiClient, item.Id);
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
page.querySelector('.seriesTimerScheduleSection').classList.add('hide');
|
|
|
|
return void hideAll(page, 'btnCancelSeriesTimer');
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function renderTrackSelections(page, instance, item, forceReload) {
|
|
|
|
const select = page.querySelector('.selectSource');
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
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;
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
|
2020-10-30 12:43:06 +01:00
|
|
|
let mediaSources = item.MediaSources;
|
2020-09-07 13:51:09 +02:00
|
|
|
|
2020-10-30 12:37:24 +01:00
|
|
|
const resolutionNames = [];
|
|
|
|
const sourceNames = [];
|
2020-09-07 13:51:09 +02:00
|
|
|
mediaSources.forEach(function (v) {
|
2020-10-18 11:53:31 +02:00
|
|
|
(v.Name.endsWith('p') || v.Name.endsWith('i')) && !Number.isNaN(parseInt(v.Name, 10)) ? resolutionNames.push(v) : sourceNames.push(v);
|
2020-09-07 13:51:09 +02:00
|
|
|
});
|
|
|
|
|
2020-09-10 09:22:58 +02:00
|
|
|
resolutionNames.sort((a, b) => parseInt(b.Name, 10) - parseInt(a.Name, 10));
|
2020-09-07 13:51:09 +02:00
|
|
|
sourceNames.sort(function(a, b) {
|
2020-10-30 12:37:24 +01:00
|
|
|
const nameA = a.Name.toUpperCase();
|
|
|
|
const nameB = b.Name.toUpperCase();
|
2020-09-07 13:51:09 +02:00
|
|
|
if (nameA < nameB) {
|
|
|
|
return -1;
|
|
|
|
} else if (nameA > nameB) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
});
|
|
|
|
|
|
|
|
mediaSources = [];
|
|
|
|
resolutionNames.forEach(v => mediaSources.push(v));
|
|
|
|
sourceNames.forEach(v => mediaSources.push(v));
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
instance._currentPlaybackMediaSources = mediaSources;
|
2020-05-04 12:44:12 +02:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
page.querySelector('.trackSelections').classList.remove('hide');
|
|
|
|
select.setLabel(globalize.translate('LabelVersion'));
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
const currentValue = select.value;
|
2020-06-17 15:45:23 +02:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
const selectedId = mediaSources[0].Id;
|
|
|
|
select.innerHTML = mediaSources.map(function (v) {
|
|
|
|
const selected = v.Id === selectedId ? ' selected' : '';
|
|
|
|
return '<option value="' + v.Id + '"' + selected + '>' + v.Name + '</option>';
|
|
|
|
}).join('');
|
2020-06-17 15:45:23 +02:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (mediaSources.length > 1) {
|
|
|
|
page.querySelector('.selectSourceContainer').classList.remove('hide');
|
|
|
|
} else {
|
|
|
|
page.querySelector('.selectSourceContainer').classList.add('hide');
|
|
|
|
}
|
2020-06-17 15:45:23 +02:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (select.value !== currentValue || forceReload) {
|
|
|
|
renderVideoSelections(page, mediaSources);
|
|
|
|
renderAudioSelections(page, mediaSources);
|
|
|
|
renderSubtitleSelections(page, mediaSources);
|
|
|
|
}
|
|
|
|
}
|
2020-06-14 21:36:18 +02:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function renderVideoSelections(page, mediaSources) {
|
|
|
|
const mediaSourceId = page.querySelector('.selectSource').value;
|
|
|
|
const mediaSource = mediaSources.filter(function (m) {
|
|
|
|
return m.Id === mediaSourceId;
|
|
|
|
})[0];
|
2020-06-14 21:36:18 +02:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
const tracks = mediaSource.MediaStreams.filter(function (m) {
|
|
|
|
return m.Type === 'Video';
|
|
|
|
});
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
const select = page.querySelector('.selectVideo');
|
2020-08-31 23:47:11 +09:00
|
|
|
select.setLabel(globalize.translate('Video'));
|
2020-08-25 15:44:01 +01:00
|
|
|
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);
|
2020-07-12 04:48:38 +09:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (resolutionText) {
|
|
|
|
titleParts.push(resolutionText);
|
|
|
|
}
|
2020-07-12 04:48:38 +09:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (v.Codec) {
|
|
|
|
titleParts.push(v.Codec.toUpperCase());
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
return '<option value="' + v.Index + '" ' + selected + '>' + (v.DisplayTitle || titleParts.join(' ')) + '</option>';
|
|
|
|
}).join('');
|
|
|
|
select.setAttribute('disabled', 'disabled');
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (tracks.length) {
|
|
|
|
page.querySelector('.selectVideoContainer').classList.remove('hide');
|
|
|
|
} else {
|
|
|
|
page.querySelector('.selectVideoContainer').classList.add('hide');
|
|
|
|
}
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
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 '<option value="' + v.Index + '" ' + selected + '>' + v.DisplayTitle + '</option>';
|
|
|
|
}).join('');
|
|
|
|
|
|
|
|
if (tracks.length > 1) {
|
|
|
|
select.removeAttribute('disabled');
|
|
|
|
} else {
|
2020-05-04 12:44:12 +02:00
|
|
|
select.setAttribute('disabled', 'disabled');
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
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 = '<option value="-1">' + globalize.translate('Off') + '</option>' + tracks.map(function (v) {
|
|
|
|
selected = v.Index === selectedId ? ' selected' : '';
|
2020-05-04 12:44:12 +02:00
|
|
|
return '<option value="' + v.Index + '" ' + selected + '>' + v.DisplayTitle + '</option>';
|
|
|
|
}).join('');
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (tracks.length > 0) {
|
2020-05-04 12:44:12 +02:00
|
|
|
select.removeAttribute('disabled');
|
2019-11-06 13:43:39 +03:00
|
|
|
} else {
|
2020-05-04 12:44:12 +02:00
|
|
|
select.setAttribute('disabled', 'disabled');
|
2019-11-06 13:43:39 +03:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
page.querySelector('.selectSubtitlesContainer').classList.remove('hide');
|
|
|
|
} else {
|
|
|
|
select.innerHTML = '';
|
|
|
|
page.querySelector('.selectSubtitlesContainer').classList.add('hide');
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
2020-08-25 15:44:01 +01:00
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function reloadPlayButtons(page, item) {
|
|
|
|
let canPlay = false;
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (item.Type == 'Program') {
|
|
|
|
const now = new Date();
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (now >= datetime.parseISO8601Date(item.StartDate, true) && now < datetime.parseISO8601Date(item.EndDate, true)) {
|
2020-05-04 12:44:12 +02:00
|
|
|
hideAll(page, 'btnPlay', true);
|
2019-11-06 13:43:39 +03:00
|
|
|
canPlay = true;
|
|
|
|
} else {
|
2020-05-04 12:44:12 +02:00
|
|
|
hideAll(page, 'btnPlay');
|
2019-11-06 13:43:39 +03:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
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;
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
const isResumable = item.UserData && item.UserData.PlaybackPositionTicks > 0;
|
|
|
|
hideAll(page, 'btnResume', isResumable);
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2021-01-11 11:54:18 +01:00
|
|
|
for (const elem of page.querySelectorAll('.btnPlay')) {
|
|
|
|
const btnPlay = elem.querySelector('.detailButton-icon');
|
|
|
|
|
|
|
|
if (isResumable) {
|
|
|
|
btnPlay.classList.replace('play_arrow', 'replay');
|
|
|
|
} else {
|
|
|
|
btnPlay.classList.replace('replay', 'play_arrow');
|
2019-11-06 13:43:39 +03:00
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
2020-08-25 15:44:01 +01:00
|
|
|
} else {
|
|
|
|
hideAll(page, 'btnPlay');
|
|
|
|
hideAll(page, 'btnResume');
|
|
|
|
hideAll(page, 'btnInstantMix');
|
|
|
|
hideAll(page, 'btnShuffle');
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2022-01-15 20:24:25 +03:00
|
|
|
if (layoutManager.tv) {
|
|
|
|
const btnResume = page.querySelector('.mainDetailButtons .btnResume');
|
|
|
|
const btnPlay = page.querySelector('.mainDetailButtons .btnPlay');
|
|
|
|
const resumeHidden = btnResume.classList.contains('hide');
|
2022-01-20 19:23:14 +03:00
|
|
|
btnResume.classList.toggle('raised', !resumeHidden);
|
|
|
|
btnPlay.classList.toggle('raised', resumeHidden);
|
2021-07-22 16:07:50 +02:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
return canPlay;
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function reloadUserDataButtons(page, item) {
|
|
|
|
let i;
|
|
|
|
let length;
|
|
|
|
const btnPlaystates = page.querySelectorAll('.btnPlaystate');
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
for (i = 0, length = btnPlaystates.length; i < length; i++) {
|
|
|
|
const btnPlaystate = btnPlaystates[i];
|
|
|
|
|
|
|
|
if (itemHelper.canMarkPlayed(item)) {
|
|
|
|
btnPlaystate.classList.remove('hide');
|
|
|
|
btnPlaystate.setItem(item);
|
|
|
|
} else {
|
|
|
|
btnPlaystate.classList.add('hide');
|
|
|
|
btnPlaystate.setItem(null);
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
const btnUserRatings = page.querySelectorAll('.btnUserRating');
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
for (i = 0, length = btnUserRatings.length; i < length; i++) {
|
|
|
|
const btnUserRating = btnUserRatings[i];
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (itemHelper.canRate(item)) {
|
|
|
|
btnUserRating.classList.remove('hide');
|
|
|
|
btnUserRating.setItem(item);
|
|
|
|
} else {
|
|
|
|
btnUserRating.classList.add('hide');
|
|
|
|
btnUserRating.setItem(null);
|
2019-11-06 13:43:39 +03:00
|
|
|
}
|
2020-08-25 15:44:01 +01:00
|
|
|
}
|
|
|
|
}
|
2020-06-16 00:32:23 +09:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function getArtistLinksHtml(artists, serverId, context) {
|
|
|
|
const html = [];
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
for (const artist of artists) {
|
|
|
|
const href = appRouter.getRouteUrl(artist, {
|
|
|
|
context: context,
|
|
|
|
itemType: 'MusicArtist',
|
|
|
|
serverId: serverId
|
|
|
|
});
|
|
|
|
html.push('<a style="color:inherit;" class="button-link" is="emby-linkbutton" href="' + href + '">' + artist.Name + '</a>');
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
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
|
|
|
|
});
|
2022-02-09 22:05:17 +03:00
|
|
|
parentNameHtml.push('<a style="color:inherit;" class="button-link" is="emby-linkbutton" href="' + parentRoute + '">' + item.SeriesName + '</a>');
|
2020-08-25 15:44:01 +01:00
|
|
|
} 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
|
|
|
|
});
|
2022-02-09 22:05:17 +03:00
|
|
|
parentNameHtml.push('<a style="color:inherit;" class="button-link" is="emby-linkbutton" href="' + parentRoute + '">' + item.SeriesName + '</a>');
|
2020-08-25 15:44:01 +01:00
|
|
|
} 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
|
|
|
|
});
|
2022-02-09 22:05:17 +03:00
|
|
|
parentNameHtml.push('<a style="color:inherit;" class="button-link" is="emby-linkbutton" href="' + parentRoute + '">' + item.SeasonName + '</a>');
|
2020-08-25 15:44:01 +01:00
|
|
|
} 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
|
2018-10-23 01:05:09 +03:00
|
|
|
});
|
2022-02-09 22:05:17 +03:00
|
|
|
parentNameHtml.push('<a style="color:inherit;" class="button-link" is="emby-linkbutton" href="' + parentRoute + '">' + item.Album + '</a>');
|
2020-08-25 15:44:01 +01:00
|
|
|
} 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];
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (parentNameHtml.length) {
|
|
|
|
if (parentNameLast) {
|
|
|
|
// Music
|
|
|
|
if (layoutManager.mobile) {
|
|
|
|
html = '<h3 class="parentName musicParentName">' + parentNameHtml.join('</br>') + '</h3>';
|
2020-04-05 00:59:37 +02:00
|
|
|
} else {
|
2022-02-09 22:05:17 +03:00
|
|
|
html = '<h3 class="parentName musicParentName focuscontainer-x">' + parentNameHtml.join(' - ') + '</h3>';
|
2020-04-05 00:59:37 +02:00
|
|
|
}
|
2019-09-11 17:59:00 +02:00
|
|
|
} else {
|
2022-02-09 22:05:17 +03:00
|
|
|
html = '<h1 class="parentName focuscontainer-x">' + tvShowHtml + '</h1>';
|
2019-09-11 17:59:00 +02:00
|
|
|
}
|
2020-08-25 15:44:01 +01:00
|
|
|
}
|
2019-09-11 17:59:00 +02:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
const name = itemHelper.getDisplayName(item, {
|
|
|
|
includeParentInfo: false
|
|
|
|
});
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (html && !parentNameLast) {
|
|
|
|
if (tvSeasonHtml) {
|
2022-02-09 22:05:17 +03:00
|
|
|
html += '<h3 class="itemName infoText subtitle focuscontainer-x">' + tvSeasonHtml + ' - ' + name + '</h3>';
|
2019-11-06 13:43:39 +03:00
|
|
|
} else {
|
2020-08-25 15:44:01 +01:00
|
|
|
html += '<h3 class="itemName infoText subtitle">' + name + '</h3>';
|
2019-11-06 13:43:39 +03:00
|
|
|
}
|
2020-08-25 15:44:01 +01:00
|
|
|
} else if (item.OriginalTitle && item.OriginalTitle != item.Name) {
|
|
|
|
html = '<h1 class="itemName infoText parentNameLast withOriginalTitle">' + name + '</h1>' + html;
|
|
|
|
} else {
|
|
|
|
html = '<h1 class="itemName infoText parentNameLast">' + name + '</h1>' + html;
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (item.OriginalTitle && item.OriginalTitle != item.Name) {
|
|
|
|
html += '<h4 class="itemName infoText originalTitle">' + item.OriginalTitle + '</h4>';
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
container.innerHTML = html;
|
|
|
|
|
|
|
|
if (html.length) {
|
|
|
|
container.classList.remove('hide');
|
|
|
|
} else {
|
|
|
|
container.classList.add('hide');
|
2019-11-28 22:46:57 +03:00
|
|
|
}
|
2020-08-25 15:44:01 +01:00
|
|
|
}
|
2019-11-28 22:46:57 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
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');
|
|
|
|
}
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function renderBackdrop(item) {
|
|
|
|
if (dom.getWindowSize().innerWidth >= 1000) {
|
|
|
|
backdrop.setBackdrops([item]);
|
|
|
|
} else {
|
|
|
|
backdrop.clearBackdrop();
|
|
|
|
}
|
|
|
|
}
|
2020-02-17 22:03:36 +01:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function renderDetailPageBackdrop(page, item, apiClient) {
|
2021-08-10 02:36:35 -04:00
|
|
|
// Details banner is disabled in user settings
|
2021-08-06 02:09:26 -04:00
|
|
|
if (!userSettings.detailsBanner()) {
|
2020-08-25 15:44:01 +01:00
|
|
|
return false;
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
|
2021-08-13 14:43:55 -04:00
|
|
|
// Disable item backdrop for books and people because they only have primary images
|
|
|
|
if (item.Type === 'Person' || item.Type === 'Book') {
|
2021-08-10 02:36:35 -04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
let imgUrl;
|
|
|
|
let hasbackdrop = false;
|
|
|
|
const itemBackdropElement = page.querySelector('#itemBackdrop');
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
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 = '';
|
|
|
|
}
|
2020-02-23 21:14:38 +01:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
return hasbackdrop;
|
|
|
|
}
|
2020-05-10 13:36:26 +02:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function reloadFromItem(instance, page, params, item, user) {
|
2020-10-17 19:08:56 +01:00
|
|
|
const apiClient = ServerConnections.getApiClient(item.ServerId);
|
2020-05-10 13:36:26 +02:00
|
|
|
|
2020-10-18 20:00:39 +01:00
|
|
|
appRouter.setTitle('');
|
2020-05-10 13:36:26 +02:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
// Start rendering the artwork first
|
|
|
|
renderImage(page, item);
|
2020-08-30 18:19:08 +02:00
|
|
|
// Save some screen real estate in TV mode
|
|
|
|
if (!layoutManager.tv) {
|
2019-11-06 13:43:39 +03:00
|
|
|
renderLogo(page, item, apiClient);
|
|
|
|
renderDetailPageBackdrop(page, item, apiClient);
|
2020-08-30 18:19:08 +02:00
|
|
|
}
|
2021-08-06 02:09:26 -04:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
renderBackdrop(item);
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
// 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);
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
renderSeriesTimerEditor(page, item, apiClient, user);
|
|
|
|
renderTimerEditor(page, item, apiClient, user);
|
|
|
|
setInitialCollapsibleState(page, item, apiClient, params.context, user);
|
|
|
|
const canPlay = reloadPlayButtons(page, item);
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
setTrailerButtonVisibility(page, item);
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (item.Type !== 'Program' || canPlay) {
|
|
|
|
hideAll(page, 'mainDetailButtons', true);
|
|
|
|
} else {
|
|
|
|
hideAll(page, 'mainDetailButtons');
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
showRecordingFields(instance, page, item, user);
|
|
|
|
const groupedVersions = (item.MediaSources || []).filter(function (g) {
|
|
|
|
return g.Type == 'Grouping';
|
|
|
|
});
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (user.Policy.IsAdministrator && groupedVersions.length) {
|
|
|
|
page.querySelector('.btnSplitVersions').classList.remove('hide');
|
|
|
|
} else {
|
|
|
|
page.querySelector('.btnSplitVersions').classList.add('hide');
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
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 {
|
2021-07-10 11:45:40 +02:00
|
|
|
const birthday = datetime.parseISO8601Date(item.PremiereDate, true);
|
|
|
|
const durationSinceBorn = intervalToDuration({ start: birthday, end: Date.now() });
|
2020-08-25 15:44:01 +01:00
|
|
|
itemBirthday.classList.remove('hide');
|
2021-07-10 11:45:40 +02:00
|
|
|
if (item.EndDate) {
|
|
|
|
itemBirthday.innerHTML = globalize.translate('BirthDateValue', birthday.toLocaleDateString());
|
|
|
|
} else {
|
|
|
|
itemBirthday.innerHTML = `${globalize.translate('BirthDateValue', birthday.toLocaleDateString())} ${globalize.translate('AgeValue', durationSinceBorn.years)}`;
|
|
|
|
}
|
2020-08-25 15:44:01 +01:00
|
|
|
} catch (err) {
|
2021-07-10 11:45:40 +02:00
|
|
|
console.error(err);
|
2020-05-04 12:44:12 +02:00
|
|
|
itemBirthday.classList.add('hide');
|
2019-11-06 13:43:39 +03:00
|
|
|
}
|
2020-08-25 15:44:01 +01:00
|
|
|
} else {
|
|
|
|
itemBirthday.classList.add('hide');
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
const itemDeathDate = page.querySelector('#itemDeathDate');
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (item.Type == 'Person' && item.EndDate) {
|
|
|
|
try {
|
2021-07-10 11:45:40 +02:00
|
|
|
const deathday = datetime.parseISO8601Date(item.EndDate, true);
|
2020-08-25 15:44:01 +01:00
|
|
|
itemDeathDate.classList.remove('hide');
|
2021-07-10 11:45:40 +02:00
|
|
|
if (item.PremiereDate) {
|
|
|
|
const birthday = datetime.parseISO8601Date(item.PremiereDate, true);
|
|
|
|
const durationSinceBorn = intervalToDuration({ start: birthday, end: deathday });
|
|
|
|
|
|
|
|
itemDeathDate.innerHTML = `${globalize.translate('DeathDateValue', deathday.toLocaleDateString())} ${globalize.translate('AgeValue', durationSinceBorn.years)}`;
|
|
|
|
} else {
|
|
|
|
itemDeathDate.innerHTML = globalize.translate('DeathDateValue', deathday.toLocaleDateString());
|
|
|
|
}
|
2020-08-25 15:44:01 +01:00
|
|
|
} catch (err) {
|
2021-07-10 11:45:40 +02:00
|
|
|
console.error(err);
|
2020-05-04 12:44:12 +02:00
|
|
|
itemDeathDate.classList.add('hide');
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
2020-08-25 15:44:01 +01:00
|
|
|
} else {
|
|
|
|
itemDeathDate.classList.add('hide');
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
const itemBirthLocation = page.querySelector('#itemBirthLocation');
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (item.Type == 'Person' && item.ProductionLocations && item.ProductionLocations.length) {
|
2021-01-05 15:47:19 +01:00
|
|
|
let location = item.ProductionLocations[0];
|
2020-10-31 19:37:00 +03:00
|
|
|
if (!layoutManager.tv && appHost.supports('externallinks')) {
|
2021-01-05 15:47:19 +01:00
|
|
|
location = `<a is="emby-linkbutton" class="button-link textlink" target="_blank" href="https://www.openstreetmap.org/search?query=${encodeURIComponent(location)}">${location}</a>`;
|
2020-10-31 18:37:24 +03:00
|
|
|
}
|
2020-08-25 15:44:01 +01:00
|
|
|
itemBirthLocation.classList.remove('hide');
|
2021-01-05 15:40:07 +01:00
|
|
|
itemBirthLocation.innerHTML = globalize.translate('BirthPlaceValue', location);
|
2020-08-25 15:44:01 +01:00
|
|
|
} else {
|
|
|
|
itemBirthLocation.classList.add('hide');
|
|
|
|
}
|
2019-05-08 07:03:59 +02:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
setPeopleHeader(page, item);
|
|
|
|
loading.hide();
|
2019-07-28 15:51:02 +02:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (item.Type === 'Book' && item.CanDownload && appHost.supports('filedownload')) {
|
|
|
|
hideAll(page, 'btnDownload', true);
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
|
2022-01-15 20:03:13 +03:00
|
|
|
autoFocus(page);
|
2020-08-25 15:44:01 +01:00
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function logoImageUrl(item, apiClient, options) {
|
|
|
|
options = options || {};
|
|
|
|
options.type = 'Logo';
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (item.ImageTags && item.ImageTags.Logo) {
|
|
|
|
options.tag = item.ImageTags.Logo;
|
|
|
|
return apiClient.getScaledImageUrl(item.Id, options);
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (item.ParentLogoImageTag) {
|
|
|
|
options.tag = item.ParentLogoImageTag;
|
|
|
|
return apiClient.getScaledImageUrl(item.ParentLogoItemId, options);
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
return null;
|
|
|
|
}
|
2020-05-10 13:36:26 +02:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function renderLogo(page, item, apiClient) {
|
|
|
|
const detailLogo = page.querySelector('.detailLogo');
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
const url = logoImageUrl(item, apiClient, {});
|
|
|
|
|
2021-03-09 09:17:04 -05:00
|
|
|
if (url) {
|
2020-08-25 15:44:01 +01:00
|
|
|
detailLogo.classList.remove('hide');
|
|
|
|
imageLoader.setLazyImage(detailLogo, url);
|
|
|
|
} else {
|
|
|
|
detailLogo.classList.add('hide');
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
2020-08-25 15:44:01 +01:00
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function showRecordingFields(instance, page, item, user) {
|
|
|
|
if (!instance.currentRecordingFields) {
|
|
|
|
const recordingFieldsElement = page.querySelector('.recordingFields');
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (item.Type == 'Program' && user.Policy.EnableLiveTvManagement) {
|
2020-08-14 08:46:34 +02:00
|
|
|
import('../../components/recordingcreator/recordingfields').then(({ default: recordingFields }) => {
|
2020-08-25 15:44:01 +01:00
|
|
|
instance.currentRecordingFields = new recordingFields({
|
|
|
|
parent: recordingFieldsElement,
|
|
|
|
programId: item.Id,
|
|
|
|
serverId: item.ServerId
|
2019-11-06 13:43:39 +03:00
|
|
|
});
|
2020-08-25 15:44:01 +01:00
|
|
|
recordingFieldsElement.classList.remove('hide');
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
recordingFieldsElement.classList.add('hide');
|
|
|
|
recordingFieldsElement.innerHTML = '';
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
}
|
2020-08-25 15:44:01 +01:00
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function renderLinks(page, item) {
|
|
|
|
const externalLinksElem = page.querySelector('.itemExternalLinks');
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
const links = [];
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (!layoutManager.tv && item.HomePageUrl) {
|
|
|
|
links.push(`<a is="emby-linkbutton" class="button-link" href="${item.HomePageUrl}" target="_blank">${globalize.translate('ButtonWebsite')}</a>`);
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (item.ExternalUrls) {
|
|
|
|
for (const url of item.ExternalUrls) {
|
|
|
|
links.push(`<a is="emby-linkbutton" class="button-link" href="${url.Url}" target="_blank">${url.Name}</a>`);
|
2019-11-06 13:43:39 +03:00
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
const html = [];
|
|
|
|
if (links.length) {
|
|
|
|
html.push(links.join(', '));
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
externalLinksElem.innerHTML = html.join(', ');
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (html.length) {
|
|
|
|
externalLinksElem.classList.remove('hide');
|
|
|
|
} else {
|
|
|
|
externalLinksElem.classList.add('hide');
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
2020-08-25 15:44:01 +01:00
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
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,
|
2021-08-06 02:09:26 -04:00
|
|
|
overlayPlayButton: layoutManager.mobile ? false : true,
|
|
|
|
action: layoutManager.mobile ? 'none' : 'play',
|
2020-08-25 15:44:01 +01:00
|
|
|
width: dom.getWindowSize().innerWidth * 0.25
|
|
|
|
});
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
elem.innerHTML = cardHtml;
|
|
|
|
imageLoader.lazyChildren(elem);
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-30 18:19:08 +02:00
|
|
|
// Avoid breaking the design by preventing focus of the poster using the keyboard.
|
|
|
|
elem.querySelector('button').tabIndex = -1;
|
2020-08-25 15:44:01 +01:00
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function renderImage(page, item) {
|
|
|
|
renderDetailImage(
|
|
|
|
page.querySelector('.detailImageContainer'),
|
|
|
|
item,
|
|
|
|
imageLoader
|
|
|
|
);
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
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');
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
2020-08-25 15:44:01 +01:00
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function renderNextUp(page, item, user) {
|
|
|
|
const section = page.querySelector('.nextUpSection');
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (item.Type != 'Series') {
|
|
|
|
return void section.classList.add('hide');
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-10-17 19:08:56 +01:00
|
|
|
ServerConnections.getApiClient(item.ServerId).getNextUpEpisodes({
|
2020-08-25 15:44:01 +01:00
|
|
|
SeriesId: item.Id,
|
2022-01-20 15:58:14 -06:00
|
|
|
UserId: user.Id,
|
2022-01-20 16:06:24 -06:00
|
|
|
Fields: 'MediaSourceCount'
|
2020-08-25 15:44:01 +01:00
|
|
|
}).then(function (result) {
|
|
|
|
if (result.Items.length) {
|
|
|
|
section.classList.remove('hide');
|
2019-11-06 13:43:39 +03:00
|
|
|
} else {
|
2020-08-25 15:44:01 +01:00
|
|
|
section.classList.add('hide');
|
2019-11-06 13:43:39 +03:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
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');
|
2019-11-06 13:43:39 +03:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
renderChildren(page, item);
|
|
|
|
} else {
|
|
|
|
page.querySelector('#childrenCollapsible').classList.add('hide');
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (item.Type == 'Series') {
|
|
|
|
renderSeriesSchedule(page, item);
|
|
|
|
renderNextUp(page, item, user);
|
|
|
|
} else {
|
|
|
|
page.querySelector('.nextUpSection').classList.add('hide');
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
renderScenes(page, item);
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2022-02-11 13:23:13 -06:00
|
|
|
if (item.SpecialFeatureCount > 0) {
|
2020-08-25 15:44:01 +01:00
|
|
|
page.querySelector('#specialsCollapsible').classList.remove('hide');
|
|
|
|
renderSpecials(page, item, user);
|
|
|
|
} else {
|
|
|
|
page.querySelector('#specialsCollapsible').classList.add('hide');
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
renderCast(page, item);
|
2020-03-08 15:50:54 -04:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
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');
|
2020-03-08 15:50:54 -04:00
|
|
|
}
|
2020-08-25 15:44:01 +01:00
|
|
|
}
|
2020-03-08 15:50:54 -04:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function toggleLineClamp(clampTarget, e) {
|
|
|
|
const expandButton = e.target;
|
|
|
|
const clampClassName = 'detail-clamp-text';
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (clampTarget.classList.contains(clampClassName)) {
|
|
|
|
clampTarget.classList.remove(clampClassName);
|
|
|
|
expandButton.innerHTML = globalize.translate('ShowLess');
|
|
|
|
} else {
|
|
|
|
clampTarget.classList.add(clampClassName);
|
|
|
|
expandButton.innerHTML = globalize.translate('ShowMore');
|
|
|
|
}
|
|
|
|
}
|
2020-05-03 17:30:19 -04:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function renderOverview(page, item) {
|
|
|
|
for (const overviewElemnt of page.querySelectorAll('.overview')) {
|
|
|
|
const overview = item.Overview || '';
|
2020-05-03 17:30:19 -04:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (overview) {
|
|
|
|
overviewElemnt.innerHTML = overview;
|
|
|
|
overviewElemnt.classList.remove('hide');
|
|
|
|
overviewElemnt.classList.add('detail-clamp-text');
|
2020-05-03 17:30:19 -04:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
// Grab the sibling element to control the expand state
|
|
|
|
const expandButton = overviewElemnt.parentElement.querySelector('.overview-expand');
|
2020-03-08 15:50:54 -04:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
// 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');
|
2019-11-06 13:43:39 +03:00
|
|
|
} else {
|
2020-08-25 15:44:01 +01:00
|
|
|
expandButton.classList.add('hide');
|
2019-11-06 13:43:39 +03:00
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
expandButton.addEventListener('click', toggleLineClamp.bind(null, overviewElemnt));
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
for (const anchor of overviewElemnt.querySelectorAll('a')) {
|
|
|
|
anchor.setAttribute('target', '_blank');
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
} else {
|
2020-08-25 15:44:01 +01:00
|
|
|
overviewElemnt.innerHTML = '';
|
|
|
|
overviewElemnt.classList.add('hide');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function renderGenres(page, item, context = inferContext(item)) {
|
|
|
|
const genres = item.GenreItems || [];
|
|
|
|
const type = context === 'music' ? 'MusicGenre' : 'Genre';
|
|
|
|
|
|
|
|
const html = genres.map(function (p) {
|
|
|
|
return '<a style="color:inherit;" class="button-link" is="emby-linkbutton" href="' + appRouter.getRouteUrl({
|
|
|
|
Name: p.Name,
|
|
|
|
Type: type,
|
|
|
|
ServerId: item.ServerId,
|
|
|
|
Id: p.Id
|
|
|
|
}, {
|
|
|
|
context: context
|
|
|
|
}) + '">' + p.Name + '</a>';
|
|
|
|
}).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 '<a style="color:inherit;" class="button-link" is="emby-linkbutton" href="' + appRouter.getRouteUrl({
|
|
|
|
Name: person.Name,
|
|
|
|
Type: 'Person',
|
|
|
|
ServerId: item.ServerId,
|
|
|
|
Id: person.Id
|
|
|
|
}, {
|
|
|
|
context: context
|
|
|
|
}) + '">' + person.Name + '</a>';
|
|
|
|
}).join(', ');
|
|
|
|
|
|
|
|
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 '<a style="color:inherit;" class="button-link" is="emby-linkbutton" href="' + appRouter.getRouteUrl({
|
|
|
|
Name: person.Name,
|
|
|
|
Type: 'Person',
|
|
|
|
ServerId: item.ServerId,
|
|
|
|
Id: person.Id
|
|
|
|
}, {
|
|
|
|
context: context
|
|
|
|
}) + '">' + person.Name + '</a>';
|
|
|
|
}).join(', ');
|
|
|
|
|
|
|
|
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
|
2020-05-10 15:41:55 +02:00
|
|
|
});
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (miscInfo.innerHTML && item.Type !== 'SeriesTimer') {
|
|
|
|
miscInfo.classList.remove('hide');
|
2020-05-10 15:41:55 +02:00
|
|
|
} else {
|
2020-08-25 15:44:01 +01:00
|
|
|
miscInfo.classList.add('hide');
|
2020-05-10 15:41:55 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
const secondaryItemMiscInfo = page.querySelectorAll('.itemMiscInfo-secondary');
|
|
|
|
|
|
|
|
for (const miscInfo of secondaryItemMiscInfo) {
|
|
|
|
mediaInfo.fillSecondaryMediaInfo(miscInfo, item, {
|
|
|
|
interactive: true
|
2019-11-06 13:43:39 +03:00
|
|
|
});
|
2020-05-10 13:36:26 +02:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (miscInfo.innerHTML && item.Type !== 'SeriesTimer') {
|
|
|
|
miscInfo.classList.remove('hide');
|
2019-11-06 13:43:39 +03:00
|
|
|
} else {
|
2020-08-25 15:44:01 +01:00
|
|
|
miscInfo.classList.add('hide');
|
2019-11-06 13:43:39 +03:00
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
2020-08-25 15:44:01 +01:00
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function renderTagline(page, item) {
|
|
|
|
const taglineElement = page.querySelector('.tagline');
|
2019-09-11 18:47:39 +02:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (item.Taglines && item.Taglines.length) {
|
|
|
|
taglineElement.classList.remove('hide');
|
|
|
|
taglineElement.innerHTML = item.Taglines[0];
|
|
|
|
} else {
|
|
|
|
taglineElement.classList.add('hide');
|
|
|
|
}
|
|
|
|
}
|
2019-09-11 18:47:39 +02:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
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);
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-30 18:19:08 +02:00
|
|
|
// Don't allow redirection to other websites from the TV layout
|
2020-10-31 19:37:00 +03:00
|
|
|
if (!layoutManager.tv && appHost.supports('externallinks')) {
|
2020-08-30 18:19:08 +02:00
|
|
|
renderLinks(page, item);
|
2020-05-10 13:36:26 +02:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
renderTags(page, item);
|
|
|
|
renderSeriesAirTime(page, item, isStatic);
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function enableScrollX() {
|
2020-08-27 17:41:10 +01:00
|
|
|
return browser.mobile && window.screen.availWidth <= 1000;
|
2020-08-25 15:44:01 +01:00
|
|
|
}
|
2019-09-11 18:47:39 +02:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function getPortraitShape(scrollX) {
|
|
|
|
if (scrollX == null) {
|
|
|
|
scrollX = enableScrollX();
|
2020-05-10 13:36:26 +02:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
return scrollX ? 'overflowPortrait' : 'portrait';
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function getSquareShape(scrollX) {
|
|
|
|
if (scrollX == null) {
|
|
|
|
scrollX = enableScrollX();
|
2020-05-10 13:36:26 +02:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
return scrollX ? 'overflowSquare' : 'square';
|
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function renderMoreFromSeason(view, item, apiClient) {
|
|
|
|
const section = view.querySelector('.moreFromSeasonSection');
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (section) {
|
|
|
|
if (item.Type !== 'Episode' || !item.SeasonId || !item.SeriesId) {
|
|
|
|
return void section.classList.add('hide');
|
2019-11-06 13:43:39 +03:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
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');
|
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
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 + '"]');
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (card) {
|
|
|
|
setTimeout(function () {
|
|
|
|
section.querySelector('.emby-scroller').toStart(card.previousSibling || card, true);
|
|
|
|
}, 100);
|
|
|
|
}
|
|
|
|
});
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
2020-08-25 15:44:01 +01:00
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function renderMoreFromArtist(view, item, apiClient) {
|
|
|
|
const section = view.querySelector('.moreFromArtistSection');
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (section) {
|
|
|
|
if (item.Type === 'MusicArtist') {
|
|
|
|
if (!apiClient.isMinServerVersion('3.4.1.19')) {
|
2020-05-04 12:44:12 +02:00
|
|
|
return void section.classList.add('hide');
|
2019-11-06 13:43:39 +03:00
|
|
|
}
|
2020-08-25 15:44:01 +01:00
|
|
|
} else if (item.Type !== 'MusicAlbum' || !item.AlbumArtists || !item.AlbumArtists.length) {
|
|
|
|
return void section.classList.add('hide');
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
const query = {
|
|
|
|
IncludeItemTypes: 'MusicAlbum',
|
|
|
|
Recursive: true,
|
|
|
|
ExcludeItemIds: item.Id,
|
2020-12-25 15:57:33 +01:00
|
|
|
SortBy: 'PremiereDate,ProductionYear,SortName',
|
2020-08-25 15:44:01 +01:00
|
|
|
SortOrder: 'Descending'
|
|
|
|
};
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (item.Type === 'MusicArtist') {
|
2021-06-29 10:24:17 -04:00
|
|
|
query.AlbumArtistIds = item.Id;
|
2020-08-25 15:44:01 +01:00
|
|
|
} else {
|
2021-06-29 10:24:17 -04:00
|
|
|
query.AlbumArtistIds = item.AlbumArtists[0].Id;
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
apiClient.getItems(apiClient.getCurrentUserId(), query).then(function (result) {
|
|
|
|
if (!result.Items.length) {
|
2020-05-04 12:44:12 +02:00
|
|
|
return void section.classList.add('hide');
|
2019-11-06 13:43:39 +03:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
section.classList.remove('hide');
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-07-30 16:07:13 +02:00
|
|
|
if (item.Type === 'MusicArtist') {
|
2020-08-25 15:44:01 +01:00
|
|
|
section.querySelector('h2').innerHTML = globalize.translate('HeaderAppearsOn');
|
2019-11-06 13:43:39 +03:00
|
|
|
} else {
|
2020-08-25 15:44:01 +01:00
|
|
|
section.querySelector('h2').innerHTML = globalize.translate('MoreFromValue', item.AlbumArtists[0].Name);
|
2019-11-06 13:43:39 +03:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
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
|
2019-11-06 13:43:39 +03:00
|
|
|
});
|
2020-08-25 15:44:01 +01:00
|
|
|
});
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
2020-08-25 15:44:01 +01:00
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
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') {
|
|
|
|
return void similarCollapsible.classList.add('hide');
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
similarCollapsible.classList.remove('hide');
|
2020-10-17 19:08:56 +01:00
|
|
|
const apiClient = ServerConnections.getApiClient(item.ServerId);
|
2020-08-25 15:44:01 +01:00
|
|
|
const options = {
|
|
|
|
userId: apiClient.getCurrentUserId(),
|
|
|
|
limit: 12,
|
2020-12-05 15:36:44 +01:00
|
|
|
fields: 'PrimaryImageAspectRatio,CanDelete'
|
2020-08-25 15:44:01 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
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) {
|
2020-05-04 12:44:12 +02:00
|
|
|
return void similarCollapsible.classList.add('hide');
|
2019-11-06 13:43:39 +03:00
|
|
|
}
|
|
|
|
|
2020-05-04 12:44:12 +02:00
|
|
|
similarCollapsible.classList.remove('hide');
|
2020-08-25 15:44:01 +01:00
|
|
|
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'
|
2019-11-06 13:43:39 +03:00
|
|
|
});
|
2020-08-25 15:44:01 +01:00
|
|
|
const similarContent = similarCollapsible.querySelector('.similarContent');
|
|
|
|
similarContent.innerHTML = html;
|
|
|
|
imageLoader.lazyChildren(similarContent);
|
|
|
|
});
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
2020-08-25 15:44:01 +01:00
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
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(',');
|
2019-11-06 13:43:39 +03:00
|
|
|
}
|
2020-08-25 15:44:01 +01:00
|
|
|
}
|
|
|
|
if (item.AirTime) {
|
|
|
|
html += ' at ' + item.AirTime;
|
|
|
|
}
|
|
|
|
if (item.Studios.length) {
|
|
|
|
if (isStatic) {
|
|
|
|
html += ' on ' + item.Studios[0].Name;
|
2019-11-06 13:43:39 +03:00
|
|
|
} else {
|
2020-08-25 15:44:01 +01:00
|
|
|
const context = inferContext(item);
|
|
|
|
const href = appRouter.getRouteUrl(item.Studios[0], {
|
|
|
|
context: context,
|
|
|
|
itemType: 'Studio',
|
|
|
|
serverId: item.ServerId
|
|
|
|
});
|
|
|
|
html += ' on <a class="textlink button-link" is="emby-linkbutton" href="' + href + '">' + item.Studios[0].Name + '</a>';
|
2019-11-06 13:43:39 +03:00
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
2020-08-25 15:44:01 +01:00
|
|
|
if (html) {
|
|
|
|
html = (item.Status == 'Ended' ? 'Aired ' : 'Airs ') + html;
|
|
|
|
seriesAirTime.innerHTML = html;
|
|
|
|
seriesAirTime.classList.remove('hide');
|
|
|
|
} else {
|
|
|
|
seriesAirTime.classList.add('hide');
|
|
|
|
}
|
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function renderTags(page, item) {
|
|
|
|
const itemTags = page.querySelector('.itemTags');
|
|
|
|
const tagElements = [];
|
|
|
|
let tags = item.Tags || [];
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (item.Type === 'Program') {
|
|
|
|
tags = [];
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
for (let i = 0, length = tags.length; i < length; i++) {
|
|
|
|
tagElements.push(tags[i]);
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (tagElements.length) {
|
|
|
|
itemTags.innerHTML = globalize.translate('TagsValue', tagElements.join(', '));
|
|
|
|
itemTags.classList.remove('hide');
|
|
|
|
} else {
|
|
|
|
itemTags.innerHTML = '';
|
|
|
|
itemTags.classList.add('hide');
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
2020-08-25 15:44:01 +01:00
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function renderChildren(page, item) {
|
|
|
|
let fields = 'ItemCounts,PrimaryImageAspectRatio,BasicSyncInfo,CanDelete,MediaSourceCount';
|
|
|
|
const query = {
|
|
|
|
ParentId: item.Id,
|
|
|
|
Fields: fields
|
|
|
|
};
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (item.Type !== 'BoxSet') {
|
|
|
|
query.SortBy = 'SortName';
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
let promise;
|
2020-10-17 19:08:56 +01:00
|
|
|
const apiClient = ServerConnections.getApiClient(item.ServerId);
|
2020-08-25 15:44:01 +01:00
|
|
|
const userId = apiClient.getCurrentUserId();
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
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') {
|
2020-12-25 15:57:33 +01:00
|
|
|
query.SortBy = 'PremiereDate,ProductionYear,SortName';
|
2020-08-25 15:44:01 +01:00
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
promise = promise || apiClient.getItems(apiClient.getCurrentUserId(), query);
|
|
|
|
promise.then(function (result) {
|
|
|
|
let html = '';
|
|
|
|
let scrollX = false;
|
|
|
|
let isList = false;
|
|
|
|
const childrenItemsContainer = page.querySelector('.childrenItemsContainer');
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (item.Type == 'MusicAlbum') {
|
2020-05-26 22:58:27 +02:00
|
|
|
const equalSet = (arr1, arr2) => arr1.every(x => arr2.indexOf(x) !== -1) && arr1.length === arr2.length;
|
|
|
|
let showArtist = false;
|
|
|
|
for (const track of result.Items) {
|
2020-08-31 18:06:53 +09:00
|
|
|
if (!equalSet(track.ArtistItems.map(x => x.Id), track.AlbumArtists.map(x => x.Id))) {
|
2020-05-26 22:58:27 +02:00
|
|
|
showArtist = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const discNumbers = result.Items.map(x => x.ParentIndexNumber);
|
2020-08-25 15:44:01 +01:00
|
|
|
html = listView.getListViewHtml({
|
|
|
|
items: result.Items,
|
|
|
|
smallIcon: true,
|
2020-05-26 22:58:27 +02:00
|
|
|
showIndex: new Set(discNumbers).size > 1 || (discNumbers.length >= 1 && discNumbers[0] > 1),
|
2020-08-25 15:44:01 +01:00
|
|
|
index: 'disc',
|
|
|
|
showIndexNumberLeft: true,
|
|
|
|
playFromHere: true,
|
|
|
|
action: 'playallfromhere',
|
|
|
|
image: false,
|
2020-05-26 22:58:27 +02:00
|
|
|
artist: showArtist,
|
2020-08-25 15:44:01 +01:00
|
|
|
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') {
|
2019-11-06 13:43:39 +03:00
|
|
|
isList = true;
|
2020-08-25 15:44:01 +01:00
|
|
|
}
|
|
|
|
scrollX = item.Type == 'Episode';
|
|
|
|
if (result.Items.length < 2 && item.Type === 'Episode') {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (item.Type === 'Episode') {
|
2019-11-06 13:43:39 +03:00
|
|
|
html = cardBuilder.getCardsHtml({
|
2018-10-23 01:05:09 +03:00
|
|
|
items: result.Items,
|
2020-08-25 15:44:01 +01:00
|
|
|
shape: 'overflowBackdrop',
|
2019-11-06 13:43:39 +03:00
|
|
|
showTitle: true,
|
2020-08-25 15:44:01 +01:00
|
|
|
displayAsSpecial: item.Type == 'Season' && item.IndexNumber,
|
|
|
|
playFromHere: true,
|
|
|
|
overlayText: true,
|
2019-11-06 13:43:39 +03:00
|
|
|
lazy: true,
|
2020-08-25 15:44:01 +01:00
|
|
|
showDetailsMenu: true,
|
2019-11-06 13:43:39 +03:00
|
|
|
overlayPlayButton: true,
|
2020-08-25 15:44:01 +01:00
|
|
|
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
|
2019-11-06 13:43:39 +03:00
|
|
|
});
|
|
|
|
}
|
2020-08-25 15:44:01 +01:00
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
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');
|
2020-05-04 12:44:12 +02:00
|
|
|
childrenItemsContainer.classList.remove('vertical-wrap');
|
2019-11-06 13:43:39 +03:00
|
|
|
} else {
|
2020-08-25 15:44:01 +01:00
|
|
|
childrenItemsContainer.classList.add('vertical-wrap');
|
|
|
|
childrenItemsContainer.classList.remove('vertical-list');
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
}
|
2020-08-25 15:44:01 +01:00
|
|
|
if (layoutManager.mobile) {
|
|
|
|
childrenItemsContainer.classList.remove('padded-right');
|
2019-11-06 13:43:39 +03:00
|
|
|
}
|
2020-08-25 15:44:01 +01:00
|
|
|
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');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function renderItemsByName(page, item) {
|
2020-08-14 08:46:34 +02:00
|
|
|
import('../../scripts/itembynamedetailpage').then(() => {
|
2020-08-25 15:44:01 +01:00
|
|
|
window.ItemsByName.renderItems(page, item);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function renderPlaylistItems(page, item) {
|
2020-08-14 08:46:34 +02:00
|
|
|
import('../../scripts/playlistedit').then(() => {
|
2020-08-25 15:44:01 +01:00
|
|
|
PlaylistViewer.render(page, item);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function renderProgramsForChannel(page, result) {
|
|
|
|
let html = '';
|
|
|
|
let currentItems = [];
|
|
|
|
let currentStartDate = null;
|
|
|
|
|
|
|
|
for (let i = 0, length = result.Items.length; i < length; i++) {
|
|
|
|
const item = result.Items[i];
|
|
|
|
const itemStartDate = datetime.parseISO8601Date(item.StartDate);
|
|
|
|
|
|
|
|
if (!(currentStartDate && currentStartDate.toDateString() === itemStartDate.toDateString())) {
|
|
|
|
if (currentItems.length) {
|
|
|
|
html += '<div class="verticalSection verticalDetailSection">';
|
|
|
|
html += '<h2 class="sectionTitle padded-left">' + datetime.toLocaleDateString(currentStartDate, {
|
|
|
|
weekday: 'long',
|
|
|
|
month: 'long',
|
|
|
|
day: 'numeric'
|
|
|
|
}) + '</h2>';
|
|
|
|
html += '<div is="emby-itemscontainer" class="vertical-list padded-left padded-right">' + listView.getListViewHtml({
|
|
|
|
items: currentItems,
|
|
|
|
enableUserDataButtons: false,
|
|
|
|
showParentTitle: true,
|
|
|
|
image: false,
|
|
|
|
showProgramTime: true,
|
|
|
|
mediaInfo: false,
|
|
|
|
parentTitleWithTitle: true
|
|
|
|
}) + '</div></div>';
|
2019-11-06 13:43:39 +03:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
currentStartDate = itemStartDate;
|
|
|
|
currentItems = [];
|
2019-11-06 13:43:39 +03:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
currentItems.push(item);
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (currentItems.length) {
|
|
|
|
html += '<div class="verticalSection verticalDetailSection">';
|
|
|
|
html += '<h2 class="sectionTitle padded-left">' + datetime.toLocaleDateString(currentStartDate, {
|
|
|
|
weekday: 'long',
|
|
|
|
month: 'long',
|
|
|
|
day: 'numeric'
|
|
|
|
}) + '</h2>';
|
|
|
|
html += '<div is="emby-itemscontainer" class="vertical-list padded-left padded-right">' + listView.getListViewHtml({
|
|
|
|
items: currentItems,
|
|
|
|
enableUserDataButtons: false,
|
|
|
|
showParentTitle: true,
|
|
|
|
image: false,
|
|
|
|
showProgramTime: true,
|
|
|
|
mediaInfo: false,
|
|
|
|
parentTitleWithTitle: true
|
|
|
|
}) + '</div></div>';
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
page.querySelector('.programGuide').innerHTML = html;
|
|
|
|
}
|
|
|
|
|
|
|
|
function renderChannelGuide(page, apiClient, item) {
|
|
|
|
if (item.Type === 'TvChannel') {
|
|
|
|
page.querySelector('.programGuideSection').classList.remove('hide');
|
2018-10-23 01:05:09 +03:00
|
|
|
apiClient.getLiveTvPrograms({
|
2020-08-25 15:44:01 +01:00
|
|
|
ChannelIds: item.Id,
|
2018-10-23 01:05:09 +03:00
|
|
|
UserId: apiClient.getCurrentUserId(),
|
2019-11-06 13:43:39 +03:00
|
|
|
HasAired: false,
|
2020-05-04 12:44:12 +02:00
|
|
|
SortBy: 'StartDate',
|
2019-11-06 13:43:39 +03:00
|
|
|
EnableTotalRecordCount: false,
|
|
|
|
EnableImages: false,
|
2018-10-23 01:05:09 +03:00
|
|
|
ImageTypeLimit: 0,
|
2020-08-25 15:44:01 +01:00
|
|
|
EnableUserData: false
|
2019-11-06 13:43:39 +03:00
|
|
|
}).then(function (result) {
|
2020-08-25 15:44:01 +01:00
|
|
|
renderProgramsForChannel(page, result);
|
2019-11-06 13:43:39 +03:00
|
|
|
});
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
2020-08-25 15:44:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
function renderSeriesSchedule(page, item) {
|
2020-10-17 19:08:56 +01:00
|
|
|
const apiClient = ServerConnections.getApiClient(item.ServerId);
|
2020-08-25 15:44:01 +01:00
|
|
|
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('#seriesScheduleSection').classList.add('hide');
|
2019-11-06 13:43:39 +03:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
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();
|
|
|
|
});
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function inferContext(item) {
|
|
|
|
if (item.Type === 'Movie' || item.Type === 'BoxSet') {
|
|
|
|
return 'movies';
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (item.Type === 'Series' || item.Type === 'Season' || item.Type === 'Episode') {
|
|
|
|
return 'tvshows';
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (item.Type === 'MusicArtist' || item.Type === 'MusicAlbum' || item.Type === 'Audio' || item.Type === 'AudioBook') {
|
|
|
|
return 'music';
|
2019-08-22 14:08:55 +02:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (item.Type === 'Program') {
|
|
|
|
return 'livetv';
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
return null;
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function filterItemsByCollectionItemType(items, typeInfo) {
|
|
|
|
return items.filter(function (item) {
|
|
|
|
if (typeInfo.mediaType) {
|
|
|
|
return item.MediaType == typeInfo.mediaType;
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
return item.Type == typeInfo.type;
|
|
|
|
});
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function canPlaySomeItemInCollection(items) {
|
|
|
|
let i = 0;
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
for (let length = items.length; i < length; i++) {
|
|
|
|
if (playbackManager.canPlay(items[i])) {
|
|
|
|
return true;
|
2019-11-06 13:43:39 +03:00
|
|
|
}
|
2020-08-25 15:44:01 +01:00
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
return false;
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function renderCollectionItems(page, parentItem, types, items) {
|
|
|
|
page.querySelector('.collectionItems').classList.remove('hide');
|
|
|
|
page.querySelector('.collectionItems').innerHTML = '';
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
for (const type of types) {
|
|
|
|
const typeItems = filterItemsByCollectionItemType(items, type);
|
2019-08-22 14:08:55 +02:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (typeItems.length) {
|
|
|
|
renderCollectionItemType(page, parentItem, type, typeItems);
|
2019-11-06 13:43:39 +03:00
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
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);
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (!items.length) {
|
|
|
|
renderCollectionItemType(page, parentItem, {
|
|
|
|
name: globalize.translate('Items')
|
|
|
|
}, items);
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
const containers = page.querySelectorAll('.collectionItemsContainer');
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
const notifyRefreshNeeded = function () {
|
|
|
|
renderChildren(page, parentItem);
|
|
|
|
};
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
for (const container of containers) {
|
|
|
|
container.notifyRefreshNeeded = notifyRefreshNeeded;
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
// if nothing in the collection can be played hide play and shuffle buttons
|
|
|
|
if (!canPlaySomeItemInCollection(items)) {
|
|
|
|
hideAll(page, 'btnPlay', false);
|
|
|
|
hideAll(page, 'btnShuffle', false);
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
// HACK: Call autoFocuser again because btnPlay may be hidden, but focused by reloadFromItem
|
|
|
|
// FIXME: Sometimes focus does not move until all (?) sections are loaded
|
2022-01-15 20:03:13 +03:00
|
|
|
autoFocus(page);
|
2020-08-25 15:44:01 +01:00
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function renderCollectionItemType(page, parentItem, type, items) {
|
|
|
|
let html = '';
|
|
|
|
html += '<div class="verticalSection">';
|
|
|
|
html += '<div class="sectionTitleContainer sectionTitleContainer-cards padded-left">';
|
|
|
|
html += '<h2 class="sectionTitle sectionTitle-cards">';
|
|
|
|
html += '<span>' + type.name + '</span>';
|
|
|
|
html += '</h2>';
|
|
|
|
html += '</div>';
|
|
|
|
html += '<div is="emby-itemscontainer" class="itemsContainer collectionItemsContainer vertical-wrap padded-left padded-right">';
|
|
|
|
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 += '</div>';
|
|
|
|
html += '</div>';
|
|
|
|
const collectionItems = page.querySelector('.collectionItems');
|
|
|
|
collectionItems.insertAdjacentHTML('beforeend', html);
|
2020-11-02 11:48:39 +01:00
|
|
|
imageLoader.lazyChildren(collectionItems.lastChild);
|
2020-08-25 15:44:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
function renderMusicVideos(page, item, user) {
|
2020-10-17 19:08:56 +01:00
|
|
|
ServerConnections.getApiClient(item.ServerId).getItems(user.Id, {
|
2020-08-25 15:44:01 +01:00
|
|
|
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');
|
2021-04-09 18:48:15 +02:00
|
|
|
const musicVideosContent = page.querySelector('#musicVideosContent');
|
2020-08-25 15:44:01 +01:00
|
|
|
musicVideosContent.innerHTML = getVideosHtml(result.Items);
|
|
|
|
imageLoader.lazyChildren(musicVideosContent);
|
|
|
|
} else {
|
|
|
|
page.querySelector('#musicVideosCollapsible').classList.add('hide');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function renderAdditionalParts(page, item, user) {
|
2020-10-17 19:08:56 +01:00
|
|
|
ServerConnections.getApiClient(item.ServerId).getAdditionalVideoParts(user.Id, item.Id).then(function (result) {
|
2020-08-25 15:44:01 +01:00
|
|
|
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');
|
2019-11-06 13:43:39 +03:00
|
|
|
}
|
2020-08-25 15:44:01 +01:00
|
|
|
});
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function renderScenes(page, item) {
|
|
|
|
let chapters = item.Chapters || [];
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (chapters.length && !chapters[0].ImageTag && (chapters = []), chapters.length) {
|
|
|
|
page.querySelector('#scenesCollapsible').classList.remove('hide');
|
|
|
|
const scenesContent = page.querySelector('#scenesContent');
|
|
|
|
|
2020-08-14 08:46:34 +02:00
|
|
|
import('../../components/cardbuilder/chaptercardbuilder').then(({ default: chaptercardbuilder }) => {
|
2020-08-25 15:44:01 +01:00
|
|
|
chaptercardbuilder.buildChapterCards(item, chapters, {
|
|
|
|
itemsContainer: scenesContent,
|
|
|
|
backdropShape: 'overflowBackdrop',
|
|
|
|
squareShape: 'overflowSquare',
|
2020-05-27 19:19:33 +03:00
|
|
|
imageBlurhashes: item.ImageBlurHashes
|
2019-11-06 13:43:39 +03:00
|
|
|
});
|
|
|
|
});
|
2020-08-25 15:44:01 +01:00
|
|
|
} 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) {
|
2020-10-17 19:08:56 +01:00
|
|
|
ServerConnections.getApiClient(item.ServerId).getSpecialFeatures(user.Id, item.Id).then(function (specials) {
|
2020-08-25 15:44:01 +01:00
|
|
|
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');
|
|
|
|
}
|
|
|
|
|
|
|
|
page.querySelector('#castCollapsible').classList.remove('hide');
|
|
|
|
const castContent = page.querySelector('#castContent');
|
|
|
|
|
2020-08-14 08:46:34 +02:00
|
|
|
import('../../components/cardbuilder/peoplecardbuilder').then(({ default: peoplecardbuilder }) => {
|
2020-08-25 15:44:01 +01:00
|
|
|
peoplecardbuilder.buildPeopleCards(people, {
|
|
|
|
itemsContainer: castContent,
|
|
|
|
coverImage: true,
|
|
|
|
serverId: item.ServerId,
|
|
|
|
shape: 'overflowPortrait',
|
|
|
|
imageBlurhashes: item.ImageBlurHashes
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function itemDetailPage() {
|
|
|
|
const self = this;
|
|
|
|
self.setInitialCollapsibleState = setInitialCollapsibleState;
|
|
|
|
self.renderDetails = renderDetails;
|
|
|
|
self.renderCast = renderCast;
|
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function bindAll(view, selector, eventName, fn) {
|
|
|
|
const elems = view.querySelectorAll(selector);
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
for (const elem of elems) {
|
|
|
|
elem.addEventListener(eventName, fn);
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
2020-08-25 15:44:01 +01:00
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function onTrackSelectionsSubmit(e) {
|
|
|
|
e.preventDefault();
|
|
|
|
return false;
|
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
window.ItemDetailPage = new itemDetailPage();
|
2020-07-29 10:05:26 +01:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
export default function (view, params) {
|
2020-10-22 00:36:38 +01:00
|
|
|
function getApiClient() {
|
|
|
|
return params.serverId ? ServerConnections.getApiClient(params.serverId) : ApiClient;
|
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function reload(instance, page, params) {
|
|
|
|
loading.show();
|
2020-05-10 13:36:26 +02:00
|
|
|
|
2020-10-22 00:36:38 +01:00
|
|
|
const apiClient = getApiClient();
|
2020-05-10 13:36:26 +02:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
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);
|
|
|
|
});
|
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function splitVersions(instance, page, apiClient, params) {
|
2020-10-18 15:18:15 +01:00
|
|
|
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);
|
2019-11-06 13:43:39 +03:00
|
|
|
});
|
2020-08-25 15:44:01 +01:00
|
|
|
});
|
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
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
|
|
|
|
};
|
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function playItem(item, startPosition) {
|
|
|
|
const playOptions = getPlayOptions(startPosition);
|
|
|
|
playOptions.items = [item];
|
|
|
|
playbackManager.play(playOptions);
|
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function playTrailer() {
|
|
|
|
playbackManager.playTrailers(currentItem);
|
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function playCurrentItem(button, mode) {
|
|
|
|
const item = currentItem;
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (item.Type === 'Program') {
|
2020-10-17 19:08:56 +01:00
|
|
|
const apiClient = ServerConnections.getApiClient(item.ServerId);
|
2020-08-25 15:44:01 +01:00
|
|
|
return void apiClient.getLiveTvChannel(item.ChannelId, apiClient.getCurrentUserId()).then(function (channel) {
|
|
|
|
playbackManager.play({
|
|
|
|
items: [channel]
|
2019-11-06 13:43:39 +03:00
|
|
|
});
|
2020-08-25 15:44:01 +01:00
|
|
|
});
|
2019-11-06 13:43:39 +03:00
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
playItem(item, item.UserData && mode === 'resume' ? item.UserData.PlaybackPositionTicks : 0);
|
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function onPlayClick() {
|
2022-02-20 19:28:36 +03:00
|
|
|
playCurrentItem(this, this.getAttribute('data-action'));
|
2020-08-25 15:44:01 +01:00
|
|
|
}
|
2020-08-03 13:11:23 +02:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function onPosterClick(e) {
|
|
|
|
itemShortcuts.onClick.call(view.querySelector('.detailImageContainer'), e);
|
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function onInstantMixClick() {
|
|
|
|
playbackManager.instantMix(currentItem);
|
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function onShuffleClick() {
|
|
|
|
playbackManager.shuffle(currentItem);
|
|
|
|
}
|
|
|
|
|
|
|
|
function onCancelSeriesTimerClick() {
|
2020-08-14 08:46:34 +02:00
|
|
|
import('../../components/recordingcreator/recordinghelper').then(({ default: recordingHelper }) => {
|
2020-08-25 15:44:01 +01:00
|
|
|
recordingHelper.cancelSeriesTimerWithConfirmation(currentItem.Id, currentItem.ServerId).then(function () {
|
|
|
|
Dashboard.navigate('livetv.html');
|
2019-11-06 13:43:39 +03:00
|
|
|
});
|
2020-08-25 15:44:01 +01:00
|
|
|
});
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function onCancelTimerClick() {
|
2020-08-14 08:46:34 +02:00
|
|
|
import('../../components/recordingcreator/recordinghelper').then(({ default: recordingHelper }) => {
|
2020-10-17 19:08:56 +01:00
|
|
|
recordingHelper.cancelTimer(ServerConnections.getApiClient(currentItem.ServerId), currentItem.TimerId).then(function () {
|
2020-08-25 15:44:01 +01:00
|
|
|
reload(self, view, params);
|
2019-11-06 13:43:39 +03:00
|
|
|
});
|
2020-08-25 15:44:01 +01:00
|
|
|
});
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function onPlayTrailerClick() {
|
|
|
|
playTrailer();
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function onDownloadClick() {
|
2020-11-08 19:44:19 +00:00
|
|
|
const downloadHref = getApiClient().getItemDownloadUrl(currentItem.Id);
|
|
|
|
download([{
|
|
|
|
url: downloadHref,
|
|
|
|
itemId: currentItem.Id,
|
|
|
|
serverId: currentItem.serverId
|
|
|
|
}]);
|
2020-08-25 15:44:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
function onMoreCommandsClick() {
|
|
|
|
const button = this;
|
|
|
|
let selectedItem = view.querySelector('.selectSource').value || currentItem.Id;
|
|
|
|
|
2020-10-22 00:36:38 +01:00
|
|
|
const apiClient = getApiClient();
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
apiClient.getItem(apiClient.getCurrentUserId(), selectedItem).then(function (item) {
|
|
|
|
selectedItem = item;
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
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);
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
});
|
|
|
|
});
|
2020-08-25 15:44:01 +01:00
|
|
|
});
|
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function onPlayerChange() {
|
|
|
|
renderTrackSelections(view, self, currentItem);
|
|
|
|
setTrailerButtonVisibility(view, currentItem);
|
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
function onWebSocketMessage(e, data) {
|
|
|
|
const msg = data;
|
2020-11-08 20:56:08 +00:00
|
|
|
const apiClient = getApiClient();
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
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];
|
2018-10-23 01:05:09 +03:00
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
if (userData) {
|
|
|
|
currentItem.UserData = userData;
|
|
|
|
reloadPlayButtons(view, currentItem);
|
2022-01-15 20:03:13 +03:00
|
|
|
autoFocus(view);
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
2019-11-06 13:43:39 +03:00
|
|
|
}
|
2020-07-29 10:05:26 +01:00
|
|
|
}
|
|
|
|
|
2020-08-25 15:44:01 +01:00
|
|
|
let currentItem;
|
|
|
|
const self = this;
|
|
|
|
|
2020-11-08 20:56:08 +00:00
|
|
|
function init() {
|
|
|
|
const apiClient = getApiClient();
|
2020-08-25 15:44:01 +01:00
|
|
|
|
2020-11-08 20:56:08 +00:00
|
|
|
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;
|
|
|
|
|
2020-12-18 10:09:45 -05:00
|
|
|
libraryMenu.setTransparentMenu(!layoutManager.mobile);
|
2020-11-08 20:56:08 +00:00
|
|
|
|
|
|
|
if (e.detail.isRestored) {
|
|
|
|
if (currentItem) {
|
|
|
|
appRouter.setTitle('');
|
|
|
|
renderTrackSelections(page, self, currentItem, true);
|
2022-02-13 12:11:53 +03:00
|
|
|
renderBackdrop(currentItem);
|
2020-11-08 20:56:08 +00:00
|
|
|
}
|
|
|
|
} 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;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
init();
|
2020-08-25 15:44:01 +01:00
|
|
|
}
|