Skip to content

Commit b3496b7

Browse files
feat: honor settings across search and backdrop flows (v1.6.1.1)
1 parent e8a496d commit b3496b7

5 files changed

Lines changed: 93 additions & 24 deletions

File tree

src/Jellyfin.Plugin.SeerrFin/Configuration/Advanced/SettingsHelper.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,12 @@ public static object BuildFrontendPayload(PluginConfiguration config)
216216
},
217217
tmdb = new
218218
{
219-
genreBackdropSelectionMode = advanced.Tmdb.GenreBackdropSelectionMode
219+
backdropImageSize = advanced.Tmdb.BackdropImageSize,
220+
posterImageSize = advanced.Tmdb.PosterImageSize,
221+
backdropLanguageFilter = advanced.Tmdb.BackdropLanguageFilter,
222+
preferOriginalLanguageImages = advanced.Tmdb.PreferOriginalLanguageImages,
223+
genreBackdropSelectionMode = advanced.Tmdb.GenreBackdropSelectionMode,
224+
fallbackToOriginalImageUrl = advanced.Tmdb.FallbackToOriginalImageUrl
220225
},
221226
letterboxd = new
222227
{

src/Jellyfin.Plugin.SeerrFin/Inject/seerrfin-modal.js

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,16 @@
5050
return 'https://image.tmdb.org/t/p/' + (size || 'original') + path;
5151
}
5252

53+
function resolveImageUrl(url) {
54+
if (!url) {
55+
return '';
56+
}
57+
if (url.startsWith('http') || url.startsWith('data:')) {
58+
return url;
59+
}
60+
return ApiClient.getUrl(url);
61+
}
62+
5363
const PLUGIN_ID = 'c8e4f2a1-9b3d-4e7f-a6c2-1d5e8f0a3b7c';
5464

5565
function getLogoImageUrl(data) {
@@ -223,6 +233,16 @@
223233
});
224234
}
225235

236+
function fetchSettingsBackdrop(mediaId, mediaType) {
237+
return ApiClient.ajax({
238+
url: ApiClient.getUrl('SeerrFin/backdrop/' + mediaType + '/' + mediaId),
239+
type: 'GET',
240+
dataType: 'json'
241+
}).catch(function () {
242+
return null;
243+
});
244+
}
245+
226246
function fetchTmdbDetailsFromBrowser(mediaId, mediaType, apiKey) {
227247
const isTv = mediaType === 'tv';
228248
const segment = isTv ? 'tv' : 'movie';
@@ -234,14 +254,20 @@
234254

235255
return Promise.all([
236256
fetchTmdbJson(detailsUrl, apiKey),
237-
fetchTmdbLogoPath(mediaId, mediaType, apiKey)
257+
fetchTmdbLogoPath(mediaId, mediaType, apiKey),
258+
fetchSettingsBackdrop(mediaId, mediaType)
238259
]).then(function (results) {
239260
const raw = results[0];
240261
const logoPath = results[1];
262+
const backdrop = results[2];
241263
const mapped = isTv ? mapTvDetails(raw) : mapMovieDetails(raw);
242264
if (logoPath) {
243265
mapped.logoPath = logoPath;
244266
}
267+
if (backdrop) {
268+
mapped.backdropUrl = resolveImageUrl(backdrop.backdropUrl || backdrop.BackdropUrl || '');
269+
mapped.backdropPath = backdrop.tmdbBackdropPath || backdrop.TmdbBackdropPath || mapped.backdropPath;
270+
}
245271
return mapped;
246272
}).catch(function (err) {
247273
console.warn('SeerrFin: TMDB details fetch failed', err);
@@ -797,7 +823,7 @@
797823
const year = (data.releaseDate || data.firstAirDate || '').substring(0, 4);
798824
const rating = data.voteAverage != null ? data.voteAverage : data.vote_average;
799825
const voteCount = data.voteCount != null ? data.voteCount : data.vote_count;
800-
const backdrop = tmdbImage(data.backdropPath || data.backdrop_path, 'original');
826+
const backdrop = resolveImageUrl(data.backdropUrl || data.backdrop_url || '') || tmdbImage(data.backdropPath || data.backdrop_path, 'original');
801827
const runtimeMinutes = data.runtime || (data.episodeRunTime && data.episodeRunTime[0]);
802828
const runtime = formatRuntime(runtimeMinutes);
803829
const endsAt = formatEndsAt(runtimeMinutes);

src/Jellyfin.Plugin.SeerrFin/Inject/seerrfin-tabs.js

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,8 @@ if (typeof window.seerrFinPlugin === 'undefined') {
438438

439439
loadDisplaySettings: function () {
440440
const self = this;
441+
const hadDisplaySettings = !!self._displaySettings;
442+
const previousSettingsKey = hadDisplaySettings ? self.getDisplaySettingsKey() : '';
441443
return ApiClient.ajax({
442444
url: ApiClient.getUrl('SeerrFin/display-settings') + '?_=' + Date.now(),
443445
type: 'GET',
@@ -510,6 +512,9 @@ if (typeof window.seerrFinPlugin === 'undefined') {
510512
};
511513
self.applyAdvancedSettings(self._displaySettings.Advanced);
512514
self.syncElegantFinFixes();
515+
if (hadDisplaySettings && previousSettingsKey !== self.getDisplaySettingsKey()) {
516+
self.clearBackdropCaches();
517+
}
513518
return self._displaySettings;
514519
}).catch(function () {
515520
self._displaySettings = {
@@ -528,6 +533,9 @@ if (typeof window.seerrFinPlugin === 'undefined') {
528533
};
529534
self.applyAdvancedSettings(self._displaySettings.Advanced);
530535
self.syncElegantFinFixes();
536+
if (hadDisplaySettings && previousSettingsKey !== self.getDisplaySettingsKey()) {
537+
self.clearBackdropCaches();
538+
}
531539
return self._displaySettings;
532540
});
533541
},
@@ -576,7 +584,12 @@ if (typeof window.seerrFinPlugin === 'undefined') {
576584
backdropLanguageFilter: requestModal.backdropLanguageFilter || requestModal.BackdropLanguageFilter || 'en,null,en-US'
577585
},
578586
tmdb: {
579-
genreBackdropSelectionMode: tmdb.genreBackdropSelectionMode || tmdb.GenreBackdropSelectionMode || 'random'
587+
backdropImageSize: tmdb.backdropImageSize || tmdb.BackdropImageSize || 'w780',
588+
posterImageSize: tmdb.posterImageSize || tmdb.PosterImageSize || 'w600_and_h900_bestv2',
589+
backdropLanguageFilter: tmdb.backdropLanguageFilter || tmdb.BackdropLanguageFilter || 'en,null,en-US',
590+
preferOriginalLanguageImages: self.readAdvancedBool(tmdb.preferOriginalLanguageImages ?? tmdb.PreferOriginalLanguageImages, false),
591+
genreBackdropSelectionMode: tmdb.genreBackdropSelectionMode || tmdb.GenreBackdropSelectionMode || 'random',
592+
fallbackToOriginalImageUrl: self.readAdvancedBool(tmdb.fallbackToOriginalImageUrl ?? tmdb.FallbackToOriginalImageUrl, true)
580593
},
581594
letterboxd: {
582595
usernamePattern: letterboxd.usernamePattern || letterboxd.UsernamePattern || '^[a-zA-Z0-9_-]{1,30}$',
@@ -744,9 +757,15 @@ if (typeof window.seerrFinPlugin === 'undefined') {
744757
return window.ApiClient.getUrl(url);
745758
},
746759

760+
clearBackdropCaches: function () {
761+
this._backdropResultCache = {};
762+
this._backdropBatchInflight = {};
763+
},
764+
747765
invalidateDisplaySettings: function () {
748766
const self = this;
749767
this._displaySettings = null;
768+
this.clearBackdropCaches();
750769
document.querySelectorAll('.seerrfin-movies-sections, .seerrfin-tv-sections, .seerrfin-search-section').forEach(function (section) {
751770
delete section.dataset.seerrfinDisplaySettings;
752771
});
@@ -1158,7 +1177,7 @@ if (typeof window.seerrFinPlugin === 'undefined') {
11581177
if (options.nativeCards === true) {
11591178
return window.seerrFinNativeUi.createDiscoverCards(this, items, Object.assign({}, options, {
11601179
forGrid: forGrid === true,
1161-
preferEnglishBackdrop: true
1180+
preferEnglishBackdrop: (((this._advancedSettings || {}).tmdb || {}).preferOriginalLanguageImages !== true)
11621181
}));
11631182
}
11641183

@@ -1384,7 +1403,7 @@ if (typeof window.seerrFinPlugin === 'undefined') {
13841403
return String(mediaType || '').toLowerCase() + ':' + String(tmdbId || '');
13851404
},
13861405

1387-
// Use English backdrops when merging batch responses into the cache
1406+
// Use English backdrops by default, unless the original-language image setting is enabled.
13881407
cacheBackdropResult: function (cacheKey, incoming) {
13891408
if (!cacheKey || !incoming || !incoming.url) {
13901409
return;
@@ -1400,6 +1419,12 @@ if (typeof window.seerrFinPlugin === 'undefined') {
14001419
return;
14011420
}
14021421

1422+
const preferOriginal = (((this._advancedSettings || {}).tmdb || {}).preferOriginalLanguageImages === true);
1423+
if (preferOriginal) {
1424+
this._backdropResultCache[cacheKey] = incoming;
1425+
return;
1426+
}
1427+
14031428
if (incoming.hasEnglishBackdrop && !existing.hasEnglishBackdrop) {
14041429
this._backdropResultCache[cacheKey] = incoming;
14051430
}

src/Jellyfin.Plugin.SeerrFin/Services/JellyseerrDiscoveryService.cs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,11 @@ public QueryResult<BaseItemDto> Search(string username, string query, string? la
102102
}
103103
}
104104

105-
int totalResults = json.Value<int?>("totalResults") ?? items.Count;
106105
return new QueryResult<BaseItemDto>
107106
{
108107
Items = items.ToArray(),
109108
StartIndex = 0,
110-
TotalRecordCount = totalResults
109+
TotalRecordCount = items.Count
111110
};
112111
}
113112
catch (Exception ex)
@@ -887,12 +886,16 @@ private static HttpRequestMessage CreateTmdbRequest(string url, string apiKey)
887886
return path.StartsWith('/') ? path : "/" + path;
888887
}
889888

890-
private static DiscoverItemFilterOptions ResolveSearchMapping() => new()
889+
private static DiscoverItemFilterOptions ResolveSearchMapping()
891890
{
892-
ApplyLanguageFilter = false,
893-
HideRequestedMedia = false,
894-
HideAvailableInLibrary = false
895-
};
891+
AdvancedDiscoverySettings discovery = AdvancedSettingsHelper.Resolve(SeerrFinPlugin.Instance.Configuration).Discovery;
892+
return new DiscoverItemFilterOptions
893+
{
894+
ApplyLanguageFilter = false,
895+
HideRequestedMedia = discovery.HideRequestedMedia,
896+
HideAvailableInLibrary = discovery.HideAvailableInLibrary
897+
};
898+
}
896899

897900
private static DiscoverItemFilterOptions ResolveMapping(PluginConfiguration config, bool useSeerrMapping)
898901
{
@@ -902,8 +905,8 @@ private static DiscoverItemFilterOptions ResolveMapping(PluginConfiguration conf
902905
return new DiscoverItemFilterOptions
903906
{
904907
ApplyLanguageFilter = false,
905-
HideRequestedMedia = false,
906-
HideAvailableInLibrary = false
908+
HideRequestedMedia = discovery.HideRequestedMedia,
909+
HideAvailableInLibrary = discovery.HideAvailableInLibrary
907910
};
908911
}
909912

src/Jellyfin.Plugin.SeerrFin/Services/TmdbBackdropService.cs

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,6 @@ public async Task<List<BackdropBatchItemDto>> GetCachedBackdropsAsync(IEnumerabl
8787
{
8888
string mediaType = item.MediaType.ToLowerInvariant();
8989
int tmdbId = item.TmdbId;
90-
string cacheKey = $"{mediaType}:{tmdbId}";
91-
92-
CachedBackdropDto? cached = TryGetCachedBackdrop(cacheKey);
93-
if (cached != null)
94-
{
95-
return ToBatchItem(mediaType, tmdbId, cached);
96-
}
9790

9891
PluginConfiguration config = SeerrFinPlugin.Instance.Configuration;
9992
string? apiKey = config.TmdbApiKey?.Trim();
@@ -103,6 +96,14 @@ public async Task<List<BackdropBatchItemDto>> GetCachedBackdropsAsync(IEnumerabl
10396
}
10497

10598
AdvancedTmdbSettings tmdbSettings = AdvancedSettingsHelper.Resolve(config).Tmdb;
99+
string cacheKey = BuildBackdropCacheKey(mediaType, tmdbId, tmdbSettings);
100+
101+
CachedBackdropDto? cached = TryGetCachedBackdrop(cacheKey, tmdbSettings);
102+
if (cached != null)
103+
{
104+
return ToBatchItem(mediaType, tmdbId, cached);
105+
}
106+
106107
BackdropPickResult pick = await TmdbBackdropHelper.FetchBackdropAsync(
107108
_httpClient,
108109
mediaType,
@@ -137,7 +138,7 @@ public async Task<List<BackdropBatchItemDto>> GetCachedBackdropsAsync(IEnumerabl
137138
return ToBatchItem(mediaType, tmdbId, dto);
138139
}
139140

140-
private CachedBackdropDto? TryGetCachedBackdrop(string cacheKey)
141+
private CachedBackdropDto? TryGetCachedBackdrop(string cacheKey, AdvancedTmdbSettings tmdbSettings)
141142
{
142143
if (!_cache.TryGetValue(cacheKey, out CachedBackdropDto? cached))
143144
{
@@ -150,7 +151,6 @@ public async Task<List<BackdropBatchItemDto>> GetCachedBackdropsAsync(IEnumerabl
150151
return null;
151152
}
152153

153-
AdvancedTmdbSettings tmdbSettings = AdvancedSettingsHelper.Resolve(SeerrFinPlugin.Instance.Configuration).Tmdb;
154154
string backdropSize = string.IsNullOrWhiteSpace(tmdbSettings.BackdropImageSize) ? "w780" : tmdbSettings.BackdropImageSize;
155155
string cachedSourceUrl = $"https://image.tmdb.org/t/p/{backdropSize}{cached.TmdbBackdropPath}";
156156
string refreshedUrl = ImageCacheHelper.GetCachedImageUrl(_imageCacheService, cachedSourceUrl, _logger);
@@ -168,6 +168,16 @@ public async Task<List<BackdropBatchItemDto>> GetCachedBackdropsAsync(IEnumerabl
168168
return null;
169169
}
170170

171+
private static string BuildBackdropCacheKey(string mediaType, int tmdbId, AdvancedTmdbSettings tmdbSettings)
172+
{
173+
string languageFilter = string.IsNullOrWhiteSpace(tmdbSettings.BackdropLanguageFilter)
174+
? "en,null,en-US"
175+
: tmdbSettings.BackdropLanguageFilter.Trim();
176+
string preferOriginal = tmdbSettings.PreferOriginalLanguageImages ? "original" : "default";
177+
178+
return $"{mediaType}:{tmdbId}:lang={languageFilter.ToLowerInvariant()}:mode={preferOriginal}";
179+
}
180+
171181
private static BackdropBatchItemDto ToBatchItem(string mediaType, int tmdbId, CachedBackdropDto cached) =>
172182
new()
173183
{

0 commit comments

Comments
 (0)