Added new setting for using episode images with NextUp/Resume instead of parent images

This commit is contained in:
Ömer Erdinç Yağmurlu 2021-07-10 11:23:31 +02:00
parent f5cf6879f9
commit 59e3427f50
8 changed files with 84 additions and 44 deletions

View file

@ -45,6 +45,7 @@
- [Camc314](https://github.com/camc314)
- [danieladov](https://github.com/danieladov)
- [Stephane Senart](https://github.com/ssenart)
- [Ömer Erdinç Yağmurlu](https://github.com/omeryagmurlu)
# Emby Contributors

View file

@ -122,6 +122,7 @@ import template from './displaySettings.template.html';
context.querySelector('#chkBlurhash').checked = userSettings.enableBlurhash();
context.querySelector('#chkBackdrops').checked = userSettings.enableBackdrops();
context.querySelector('#chkDetailsBanner').checked = userSettings.detailsBanner();
context.querySelector('#chkUseEpisodeImagesInNextUp').checked = userSettings.useEpisodeImagesInNextUpAndResume();
context.querySelector('#selectLanguage').value = userSettings.language() || '';
context.querySelector('.selectDateTimeLocale').value = userSettings.dateTimeLocale() || '';
@ -156,6 +157,7 @@ import template from './displaySettings.template.html';
userSettingsInstance.enableBlurhash(context.querySelector('#chkBlurhash').checked);
userSettingsInstance.enableBackdrops(context.querySelector('#chkBackdrops').checked);
userSettingsInstance.detailsBanner(context.querySelector('#chkDetailsBanner').checked);
userSettingsInstance.useEpisodeImagesInNextUpAndResume(context.querySelector('#chkUseEpisodeImagesInNextUp').checked);
if (user.Id === apiClient.getCurrentUserId()) {
skinManager.setTheme(userSettingsInstance.theme());

View file

@ -225,6 +225,14 @@
<div class="fieldDescription checkboxFieldDescription">${DisplayMissingEpisodesWithinSeasonsHelp}</div>
</div>
<div class="checkboxContainer checkboxContainer-withDescription fldUseEpisodeImagesInNextUp">
<label>
<input type="checkbox" is="emby-checkbox" id="chkUseEpisodeImagesInNextUp" />
<span>${UseEpisodeImagesInNextUp}</span>
</label>
<div class="fieldDescription checkboxFieldDescription">${UseEpisodeImagesInNextUpHelp}</div>
</div>
<button is="emby-button" type="submit" class="raised button-submit block btnSave hide">
<span>${Save}</span>
</button>

View file

@ -144,17 +144,17 @@ import ServerConnections from '../ServerConnections';
} else if (section === 'librarybuttons') {
loadlibraryButtons(elem, apiClient, user, userSettings, userViews);
} else if (section === 'resume') {
return loadResume(elem, apiClient, 'HeaderContinueWatching', 'Video');
return loadResume(elem, apiClient, 'HeaderContinueWatching', 'Video', userSettings);
} else if (section === 'resumeaudio') {
return loadResume(elem, apiClient, 'HeaderContinueListening', 'Audio');
return loadResume(elem, apiClient, 'HeaderContinueListening', 'Audio', userSettings);
} else if (section === 'activerecordings') {
loadLatestLiveTvRecordings(elem, true, apiClient);
} else if (section === 'nextup') {
loadNextUp(elem, apiClient);
loadNextUp(elem, apiClient, userSettings);
} else if (section === 'onnow' || section === 'livetv') {
return loadOnNow(elem, apiClient, user);
} else if (section === 'resumebook') {
return loadResume(elem, apiClient, 'HeaderContinueReading', 'Book');
return loadResume(elem, apiClient, 'HeaderContinueReading', 'Book', userSettings);
} else {
elem.innerHTML = '';
return Promise.resolve();
@ -374,7 +374,7 @@ import ServerConnections from '../ServerConnections';
'Video': 'videoplayback,markplayed'
};
function loadResume(elem, apiClient, headerText, mediaType) {
function loadResume(elem, apiClient, headerText, mediaType, userSettings) {
let html = '';
const dataMonitor = dataMonitorHints[mediaType] || 'markplayed';
@ -397,7 +397,7 @@ import ServerConnections from '../ServerConnections';
const itemsContainer = elem.querySelector('.itemsContainer');
itemsContainer.fetchData = getItemsToResumeFn(mediaType, apiClient.serverId());
itemsContainer.getItemsHtml = getItemsToResumeHtml;
itemsContainer.getItemsHtml = getItemsToResumeHtmlFn(userSettings.useEpisodeImagesInNextUpAndResume());
itemsContainer.parentContainer = elem;
}
@ -428,25 +428,28 @@ import ServerConnections from '../ServerConnections';
};
}
function getItemsToResumeHtml(items) {
const cardLayout = false;
return cardBuilder.getCardsHtml({
items: items,
preferThumb: true,
defaultShape: getThumbShape(),
overlayText: false,
showTitle: true,
showParentTitle: true,
lazy: true,
showDetailsMenu: true,
overlayPlayButton: true,
context: 'home',
centerText: !cardLayout,
allowBottomPadding: false,
cardLayout: cardLayout,
showYear: true,
lines: 2
});
function getItemsToResumeHtmlFn(useEpisodeImages) {
return function (items) {
const cardLayout = false;
return cardBuilder.getCardsHtml({
items: items,
preferThumb: true,
inheritThumb: !useEpisodeImages,
defaultShape: getThumbShape(),
overlayText: false,
showTitle: true,
showParentTitle: true,
lazy: true,
showDetailsMenu: true,
overlayPlayButton: true,
context: 'home',
centerText: !cardLayout,
allowBottomPadding: false,
cardLayout: cardLayout,
showYear: true,
lines: 2
});
}
}
function getOnNowFetchFn(serverId) {
@ -607,25 +610,28 @@ import ServerConnections from '../ServerConnections';
};
}
function getNextUpItemsHtml(items) {
const cardLayout = false;
return cardBuilder.getCardsHtml({
items: items,
preferThumb: true,
shape: getThumbShape(),
overlayText: false,
showTitle: true,
showParentTitle: true,
lazy: true,
overlayPlayButton: true,
context: 'home',
centerText: !cardLayout,
allowBottomPadding: !enableScrollX(),
cardLayout: cardLayout
});
function getNextUpItemsHtmlFn(useEpisodeImages) {
return function (items) {
const cardLayout = false;
return cardBuilder.getCardsHtml({
items: items,
preferThumb: true,
inheritThumb: !useEpisodeImages,
shape: getThumbShape(),
overlayText: false,
showTitle: true,
showParentTitle: true,
lazy: true,
overlayPlayButton: true,
context: 'home',
centerText: !cardLayout,
allowBottomPadding: !enableScrollX(),
cardLayout: cardLayout
});
};
}
function loadNextUp(elem, apiClient) {
function loadNextUp(elem, apiClient, userSettings) {
let html = '';
html += '<div class="sectionTitleContainer sectionTitleContainer-cards padded-left">';
@ -660,7 +666,7 @@ import ServerConnections from '../ServerConnections';
const itemsContainer = elem.querySelector('.itemsContainer');
itemsContainer.fetchData = getNextUpFetchFn(apiClient.serverId());
itemsContainer.getItemsHtml = getNextUpItemsHtml;
itemsContainer.getItemsHtml = getNextUpItemsHtmlFn(userSettings.useEpisodeImagesInNextUpAndResume());
itemsContainer.parentContainer = elem;
}

View file

@ -1115,7 +1115,11 @@ class ItemsView {
let imageType = userSettings.get(basekey + '-imageType');
if (!imageType && params.type === 'nextup') {
imageType = 'thumb';
if (userSettings.useEpisodeImagesInNextUpAndResume()) {
imageType = 'primary';
} else {
imageType = 'thumb';
}
}
return {

View file

@ -119,6 +119,7 @@ import autoFocuser from '../../components/autoFocuser';
cardBuilder.buildCards(result.Items, {
itemsContainer: container,
preferThumb: true,
inheritThumb: !userSettings.useEpisodeImagesInNextUpAndResume(),
shape: getThumbShape(),
scalable: true,
overlayPlayButton: true,
@ -197,6 +198,7 @@ import autoFocuser from '../../components/autoFocuser';
parentContainer: section,
itemsContainer: container,
preferThumb: true,
inheritThumb: !userSettings.useEpisodeImagesInNextUpAndResume(),
shape: 'backdrop',
scalable: true,
showTitle: true,

View file

@ -253,6 +253,20 @@ export class UserSettings {
return val !== 'false';
}
/**
* Get or set 'Use Episode Images in Next Up and Continue Watching' state.
* @param {string|boolean|undefined} val - Flag to enable 'Use Episode Images in Next Up and Continue Watching' or undefined.
* @return {boolean} 'Use Episode Images in Next Up' state.
*/
useEpisodeImagesInNextUpAndResume(val) {
if (val !== undefined) {
return this.set('useEpisodeImagesInNextUpAndResume', val.toString(), true);
}
val = this.get('useEpisodeImagesInNextUpAndResume', true);
return val === 'true';
}
/**
* Get or set language.
* @param {string|undefined} val - Language.
@ -494,6 +508,7 @@ export const enableFastFadein = currentSettings.enableFastFadein.bind(currentSet
export const enableBlurhash = currentSettings.enableBlurhash.bind(currentSettings);
export const enableBackdrops = currentSettings.enableBackdrops.bind(currentSettings);
export const detailsBanner = currentSettings.detailsBanner.bind(currentSettings);
export const useEpisodeImagesInNextUpAndResume = currentSettings.useEpisodeImagesInNextUpAndResume.bind(currentSettings);
export const language = currentSettings.language.bind(currentSettings);
export const dateTimeLocale = currentSettings.dateTimeLocale.bind(currentSettings);
export const chromecastVersion = currentSettings.chromecastVersion.bind(currentSettings);

View file

@ -1426,6 +1426,8 @@
"Upload": "Upload",
"UseDoubleRateDeinterlacing": "Double the frame rate when deinterlacing",
"UseDoubleRateDeinterlacingHelp": "This setting uses the field rate when deinterlacing, often referred to as bob deinterlacing, which doubles the frame rate of the video to provide full motion like what you would see when viewing interlaced video on a TV.",
"UseEpisodeImagesInNextUp": "Use episode images in Next Up and Continue Watching sections",
"UseEpisodeImagesInNextUpHelp": "Next Up and Continue Watching sections will use episode images as thumbnails instead of the primary thumbnail of the show.",
"UserAgentHelp": "Supply a custom user-agent HTTP header.",
"UserProfilesIntro": "Jellyfin includes support for user profiles with granular display settings, play state, and parental controls.",
"ValueAlbumCount": "{0} albums",