From 912e23cb67895bdad451477d622494bb6d9f85b7 Mon Sep 17 00:00:00 2001 From: Pavan Thanuj Upadrasta Date: Fri, 6 Feb 2026 22:32:53 +0000 Subject: [PATCH 1/5] Add Enable Trailers to Plugin Config --- .../Configuration/PluginConfiguration.cs | 2 ++ .../Configuration/config.html | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/Jellyfin.Plugin.MediaBar/Configuration/PluginConfiguration.cs b/src/Jellyfin.Plugin.MediaBar/Configuration/PluginConfiguration.cs index d74bcdf..8e8a9a5 100644 --- a/src/Jellyfin.Plugin.MediaBar/Configuration/PluginConfiguration.cs +++ b/src/Jellyfin.Plugin.MediaBar/Configuration/PluginConfiguration.cs @@ -46,6 +46,8 @@ namespace Jellyfin.Plugin.MediaBar.Configuration public int FadeTransitionDuration { get; set; } = -1; public bool SlideAnimationEnabled { get; set; } = true; + + public bool EnableTrailers { get; set; } = true; } public class ImageSvgs diff --git a/src/Jellyfin.Plugin.MediaBar/Configuration/config.html b/src/Jellyfin.Plugin.MediaBar/Configuration/config.html index a5c4e49..e75cbdd 100644 --- a/src/Jellyfin.Plugin.MediaBar/Configuration/config.html +++ b/src/Jellyfin.Plugin.MediaBar/Configuration/config.html @@ -132,6 +132,17 @@
Do the slides animate while they're visible? (the zooming in effect, can be quite performance heavy)
+
+ +
Enable trailer playback on the media bar slides?
+

@@ -198,6 +209,7 @@ PreloadCount: parseInt(document.querySelector("[data-id=numPreloadCount]").value, 10), FadeTransitionDuration: parseInt(document.querySelector("[data-id=numFadeTransitionDuration]").value, 10), SlideAnimationEnabled: document.querySelector("[data-id=chkSlideAnimationEnabled]").checked, + EnableTrailers: document.querySelector("[data-id=chkEnableTrailers]").checked, } }; @@ -235,6 +247,7 @@ document.querySelector("[data-id=numPreloadCount]").value = config.WebConfig.PreloadCount; document.querySelector("[data-id=numFadeTransitionDuration]").value = config.WebConfig.FadeTransitionDuration; document.querySelector("[data-id=chkSlideAnimationEnabled]").checked = config.WebConfig.SlideAnimationEnabled; + document.querySelector("[data-id=chkEnableTrailers]").checked = config.WebConfig.EnableTrailers; }) .catch(function (error) { console.error(error); From d041b4947115f83a96e74690db0dd81f2bf78e86 Mon Sep 17 00:00:00 2001 From: Pavan Thanuj Upadrasta Date: Fri, 6 Feb 2026 22:53:55 +0000 Subject: [PATCH 2/5] Pause/resume trailers on page visibility Bump slideshow version to v4.1.0 and add page-visibility handling for trailer playback. Introduces STATE flags (pageVisible, trailerPlaying) and a VisibilityObserver.handlePageVisibilityChange with a visibilitychange listener to pause trailers when the tab is hidden and resume them only when the page is visible and slideshow isn't paused. Stops the auto-advance timer while a trailer is playing and restarts/advances appropriately when trailers end; ensures trailerPlaying is reset when switching slides. Also adds defensive checks, console logs and error handling for player play/pause operations, and falls back to the slide timer if the page is not visible. --- slideshowpure.js | 68 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 63 insertions(+), 5 deletions(-) diff --git a/slideshowpure.js b/slideshowpure.js index a420ff9..85994d3 100644 --- a/slideshowpure.js +++ b/slideshowpure.js @@ -1,5 +1,5 @@ /* - * Jellyfin Slideshow by M0RPH3US v4.0.0 + * Jellyfin Slideshow by M0RPH3US v4.1.0 */ //Core Module Configuration @@ -51,6 +51,8 @@ const STATE = { players: {}, ytPromise: null, isMuted: true, + pageVisible: true, + trailerPlaying: false, }, }; @@ -1018,6 +1020,38 @@ class SlideTimer { * Observer for handling slideshow visibility based on current page */ const VisibilityObserver = { + /** + * Handles page visibility changes (tab switching, minimizing) + */ + handlePageVisibilityChange() { + STATE.slideshow.pageVisible = !document.hidden; + + const currentId = STATE.slideshow.itemIds[STATE.slideshow.currentSlideIndex]; + const player = STATE.slideshow.players[currentId]; + + if (document.hidden) { + // Page is hidden (tab switched or minimized) + if (player && typeof player.pauseVideo === 'function') { + try { + player.pauseVideo(); + console.log('🎬 Trailer paused due to tab switch'); + } catch (e) { + console.warn('Error pausing trailer:', e); + } + } + } else { + // Page is visible again + if (player && typeof player.playVideo === 'function' && STATE.slideshow.trailerPlaying && !STATE.slideshow.isPaused) { + try { + player.playVideo(); + console.log('🎬 Trailer resumed after tab switch'); + } catch (e) { + console.warn('Error resuming trailer:', e); + } + } + } + }, + updateVisibility() { const activeTab = document.querySelector(".emby-tab-button-active"); const container = document.getElementById("slides-container"); @@ -1046,6 +1080,11 @@ const VisibilityObserver = { * Initializes visibility observer */ init() { + // Add page visibility change listener for tab switching + document.addEventListener('visibilitychange', () => { + this.handlePageVisibilityChange(); + }); + console.log('✅ Page visibility observer initialized'); const observer = new MutationObserver(this.updateVisibility); observer.observe(document.body, { childList: true, subtree: true }); @@ -1597,6 +1636,9 @@ const SlideshowManager = { } } + // Reset trailer playing state when switching slides + STATE.slideshow.trailerPlaying = false; + const prevSlide = document.querySelector( `.slide[data-item-id="${prevItemId}"]`, ); @@ -1647,7 +1689,8 @@ const SlideshowManager = { setTimeout(() => { if ( STATE.slideshow.currentSlideIndex === index && - !STATE.slideshow.isPaused + !STATE.slideshow.isPaused && + STATE.slideshow.pageVisible ) { const player = STATE.slideshow.players[currentItemId]; @@ -1663,11 +1706,15 @@ const SlideshowManager = { player.seekTo(0); player.playVideo(); } catch (e) { + console.warn('Error playing trailer, falling back to timer:', e); fallbackToTimer(); } } else { fallbackToTimer(); } + } else { + // Page not visible or paused, use timer + fallbackToTimer(); } }, 3500); } else { @@ -1811,6 +1858,7 @@ const SlideshowManager = { pauseButton.setAttribute("title", playLabel); if (player && typeof player.pauseVideo === "function") { player.pauseVideo(); + // Keep trailerPlaying state - we'll resume when unpaused } } else { if (STATE.slideshow.slideInterval) STATE.slideshow.slideInterval.start(); @@ -1822,7 +1870,8 @@ const SlideshowManager = { pauseButton.setAttribute("aria-label", pauseLabel); pauseButton.setAttribute("title", pauseLabel); - if (player && typeof player.playVideo === "function") { + if (player && typeof player.playVideo === "function" && STATE.slideshow.trailerPlaying) { + // Resume trailer if it was playing player.playVideo(); } } @@ -1934,13 +1983,22 @@ const SlideshowManager = { if (container) container.classList.add("active"); if (backdrop) backdrop.classList.add("with-video"); if (plotContainer) plotContainer.classList.add("with-video"); + // Stop the auto-advance timer while trailer is playing if (STATE.slideshow.slideInterval) STATE.slideshow.slideInterval.stop(); + STATE.slideshow.trailerPlaying = true; + console.log('🎬 Trailer playing - slide timer stopped'); + } else if (event.data === YT.PlayerState.PAUSED) { + // Only set trailerPlaying to false if paused by user action (not by visibility change) + if (STATE.slideshow.pageVisible) { + STATE.slideshow.trailerPlaying = false; + } } else if (event.data === YT.PlayerState.ENDED) { if (container) container.classList.remove("active"); if (backdrop) backdrop.classList.remove("with-video"); if (plotContainer) plotContainer.classList.remove("with-video"); - if (STATE.slideshow.slideInterval) - STATE.slideshow.slideInterval.restart(); + STATE.slideshow.trailerPlaying = false; + console.log('🎬 Trailer ended - advancing to next slide'); + // Move to next slide when trailer ends this.nextSlide(); } }, From b5b7a0298ba35c688c1591c596fe91f5c0a4c52a Mon Sep 17 00:00:00 2001 From: Pavan Thanuj Upadrasta Date: Fri, 6 Feb 2026 22:53:58 +0000 Subject: [PATCH 3/5] Update index.html --- src/Jellyfin.Plugin.MediaBar/Inject/index.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Jellyfin.Plugin.MediaBar/Inject/index.html b/src/Jellyfin.Plugin.MediaBar/Inject/index.html index 96b23a4..052815b 100644 --- a/src/Jellyfin.Plugin.MediaBar/Inject/index.html +++ b/src/Jellyfin.Plugin.MediaBar/Inject/index.html @@ -1,5 +1,5 @@ - - + + + +