diff --git a/frontend/static/js/app.js b/frontend/static/js/app.js index 7ec7cd34..f3bd455f 100644 --- a/frontend/static/js/app.js +++ b/frontend/static/js/app.js @@ -2404,6 +2404,13 @@ let huntarrUI = { // Initialize when document is ready document.addEventListener('DOMContentLoaded', function() { + // Initialize TMDB image cache first + if (typeof tmdbImageCache !== 'undefined') { + tmdbImageCache.init().catch(error => { + console.error('[app.js] Failed to initialize TMDB image cache:', error); + }); + } + huntarrUI.init(); // Initialize our enhanced UI features diff --git a/frontend/static/js/modules/features/requestarr/requestarr-content.js b/frontend/static/js/modules/features/requestarr/requestarr-content.js index cfbbab8e..3cf0c705 100644 --- a/frontend/static/js/modules/features/requestarr/requestarr-content.js +++ b/frontend/static/js/modules/features/requestarr/requestarr-content.js @@ -862,6 +862,20 @@ export class RequestarrContent { `; + // Load and cache image asynchronously after card is created + if (posterUrl && !posterUrl.includes('./static/images/') && window.getCachedTMDBImage && window.tmdbImageCache) { + const imgElement = card.querySelector('.media-card-poster img'); + if (imgElement) { + window.getCachedTMDBImage(posterUrl, window.tmdbImageCache).then(cachedUrl => { + if (cachedUrl && cachedUrl !== posterUrl) { + imgElement.src = cachedUrl; + } + }).catch(err => { + console.error('[RequestarrContent] Failed to cache image:', err); + }); + } + } + const posterDiv = card.querySelector('.media-card-poster'); const requestBtn = card.querySelector('.media-card-request-btn'); const hideBtn = card.querySelector('.media-card-hide-btn'); diff --git a/frontend/static/js/modules/features/requestarr/requestarr-modal.js b/frontend/static/js/modules/features/requestarr/requestarr-modal.js index e414bb32..35222e34 100644 --- a/frontend/static/js/modules/features/requestarr/requestarr-modal.js +++ b/frontend/static/js/modules/features/requestarr/requestarr-modal.js @@ -85,8 +85,10 @@ export class RequestarrModal { finalDefault: defaultInstance }); + const backdropUrl = data.backdrop_path || ''; + let modalHTML = ` -
+
@@ -646,6 +648,21 @@ export class RequestarrModal { } document.body.appendChild(modal); + + // Cache backdrop image asynchronously after modal is in DOM + const backdropUrl = this.core.currentModalData?.backdrop_path; + if (backdropUrl && !backdropUrl.includes('./static/images/') && window.getCachedTMDBImage && window.tmdbImageCache) { + const header = modal.querySelector('.request-modal-header'); + if (header) { + window.getCachedTMDBImage(backdropUrl, window.tmdbImageCache).then(cachedUrl => { + if (cachedUrl && cachedUrl !== backdropUrl) { + header.style.backgroundImage = `url(${cachedUrl})`; + } + }).catch(err => { + console.error('[RequestarrModal] Failed to cache backdrop:', err); + }); + } + } } closeModal() { diff --git a/frontend/static/js/modules/features/requestarr/requestarr-settings.js b/frontend/static/js/modules/features/requestarr/requestarr-settings.js index b9d9cf65..17d723a5 100644 --- a/frontend/static/js/modules/features/requestarr/requestarr-settings.js +++ b/frontend/static/js/modules/features/requestarr/requestarr-settings.js @@ -34,9 +34,11 @@ export class RequestarrSettings { if (data.requests && data.requests.length > 0) { container.innerHTML = ''; - data.requests.forEach(request => { - container.appendChild(this.createHistoryItem(request)); - }); + // Use Promise.all to wait for all async createHistoryItem calls + const items = await Promise.all( + data.requests.map(request => this.createHistoryItem(request)) + ); + items.forEach(item => container.appendChild(item)); } else { container.innerHTML = '

No request history

'; } @@ -46,7 +48,7 @@ export class RequestarrSettings { } } - createHistoryItem(request) { + async createHistoryItem(request) { const item = document.createElement('div'); item.className = 'history-item'; @@ -66,6 +68,19 @@ export class RequestarrSettings {
`; + // Load and cache image asynchronously + if (posterUrl && !posterUrl.includes('./static/images/') && window.getCachedTMDBImage && window.tmdbImageCache) { + try { + const cachedUrl = await window.getCachedTMDBImage(posterUrl, window.tmdbImageCache); + if (cachedUrl && cachedUrl !== posterUrl) { + const imgElement = item.querySelector('.history-poster img'); + if (imgElement) imgElement.src = cachedUrl; + } + } catch (err) { + console.error('[RequestarrSettings] Failed to cache history image:', err); + } + } + return item; } @@ -362,7 +377,7 @@ export class RequestarrSettings { }; } - createHiddenMediaCard(item) { + async createHiddenMediaCard(item) { const card = document.createElement('div'); card.className = 'media-card'; card.setAttribute('data-tmdb-id', item.tmdb_id); @@ -379,6 +394,19 @@ export class RequestarrSettings {
`; + // Load and cache image asynchronously + if (posterUrl && !posterUrl.includes('./static/images/') && window.getCachedTMDBImage && window.tmdbImageCache) { + try { + const cachedUrl = await window.getCachedTMDBImage(posterUrl, window.tmdbImageCache); + if (cachedUrl && cachedUrl !== posterUrl) { + const imgElement = card.querySelector('.media-card-poster img'); + if (imgElement) imgElement.src = cachedUrl; + } + } catch (err) { + console.error('[RequestarrSettings] Failed to cache hidden media image:', err); + } + } + const unhideBtn = card.querySelector('.media-card-unhide-btn'); if (unhideBtn) { unhideBtn.addEventListener('click', async (e) => { diff --git a/frontend/static/js/modules/features/settings/core.js b/frontend/static/js/modules/features/settings/core.js index 064b7dbd..ab143654 100644 --- a/frontend/static/js/modules/features/settings/core.js +++ b/frontend/static/js/modules/features/settings/core.js @@ -757,6 +757,7 @@ window.SettingsForms = { enable_requestarr: getVal('enable_requestarr', true), low_usage_mode: getVal('low_usage_mode', true), show_trending: getVal('show_trending', true), + tmdb_image_cache_days: parseInt(container.querySelector('#tmdb_image_cache_days')?.value || '7'), auth_mode: (container.querySelector('#auth_mode') && container.querySelector('#auth_mode').value) || 'login', ssl_verify: getVal('ssl_verify', true), base_url: getVal('base_url', ''), diff --git a/frontend/static/js/modules/features/settings/general.js b/frontend/static/js/modules/features/settings/general.js index b055588d..6dfff1c6 100644 --- a/frontend/static/js/modules/features/settings/general.js +++ b/frontend/static/js/modules/features/settings/general.js @@ -246,6 +246,16 @@ box-shadow: 0 4px 12px rgba(90, 109, 137, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.1); ">

Display Settings

+
+ + +

Cache TMDB images to reduce load times and API usage. Missing images will still attempt to load. Set to "Disabled" to always fetch fresh images.

+