diff --git a/Jellyfin.Plugin.MediaBarEnhanced/Web/mediaBarEnhanced.css b/Jellyfin.Plugin.MediaBarEnhanced/Web/mediaBarEnhanced.css index 000a975..c97c176 100644 --- a/Jellyfin.Plugin.MediaBarEnhanced/Web/mediaBarEnhanced.css +++ b/Jellyfin.Plugin.MediaBarEnhanced/Web/mediaBarEnhanced.css @@ -999,14 +999,3 @@ .layout-tv .backdrop-container{ top: -5%; } - -/* .layout-tv .video-backdrop { - mask-image: linear-gradient(to top, - #fff0 2%, - rgb(0 0 0 / 0.5) 6%, - #000000 8%); - -webkit-mask-image: linear-gradient(to top, - #fff0 2%, - rgb(0 0 0 / 0.5) 6%, - #000000 8%); -} */ diff --git a/Jellyfin.Plugin.MediaBarEnhanced/Web/mediaBarEnhanced.js b/Jellyfin.Plugin.MediaBarEnhanced/Web/mediaBarEnhanced.js index 8411771..2d5f7a9 100644 --- a/Jellyfin.Plugin.MediaBarEnhanced/Web/mediaBarEnhanced.js +++ b/Jellyfin.Plugin.MediaBarEnhanced/Web/mediaBarEnhanced.js @@ -1432,16 +1432,19 @@ const VisibilityObserver = { // If a full screen video player is active, hide slideshow and stop playback if ((videoPlayer && !videoPlayer.classList.contains('hide')) || (trailerPlayer && !trailerPlayer.classList.contains('hide'))) { - const container = document.getElementById("slides-container"); - if (container) { - container.style.display = "none"; - container.style.visibility = "hidden"; - container.style.pointerEvents = "none"; + if (this._lastVisibleState !== 'player-active') { + this._lastVisibleState = 'player-active'; + const container = document.getElementById("slides-container"); + if (container) { + container.style.display = "none"; + container.style.visibility = "hidden"; + container.style.pointerEvents = "none"; + } + if (STATE.slideshow.slideInterval) { + STATE.slideshow.slideInterval.stop(); + } + SlideshowManager.stopAllPlayback(); } - if (STATE.slideshow.slideInterval) { - STATE.slideshow.slideInterval.stop(); - } - SlideshowManager.stopAllPlayback(); return; } @@ -1456,20 +1459,27 @@ const VisibilityObserver = { activeTab && activeTab.getAttribute("data-index") === "0"; - container.style.display = isVisible ? "block" : "none"; - container.style.visibility = isVisible ? "visible" : "hidden"; - container.style.pointerEvents = isVisible ? "auto" : "none"; + const newState = isVisible ? 'visible' : 'hidden'; + + // Only update DOM and trigger actions when state actually changes + if (this._lastVisibleState !== newState) { + this._lastVisibleState = newState; + + container.style.display = isVisible ? "block" : "none"; + container.style.visibility = isVisible ? "visible" : "hidden"; + container.style.pointerEvents = isVisible ? "auto" : "none"; - if (isVisible) { - if (STATE.slideshow.slideInterval && !STATE.slideshow.isPaused) { - STATE.slideshow.slideInterval.start(); - SlideshowManager.resumeActivePlayback(); + if (isVisible) { + if (STATE.slideshow.slideInterval && !STATE.slideshow.isPaused) { + STATE.slideshow.slideInterval.start(); + SlideshowManager.resumeActivePlayback(); + } + } else { + if (STATE.slideshow.slideInterval) { + STATE.slideshow.slideInterval.stop(); + } + SlideshowManager.stopAllPlayback(); } - } else { - if (STATE.slideshow.slideInterval) { - STATE.slideshow.slideInterval.stop(); - } - SlideshowManager.stopAllPlayback(); } }, @@ -1477,7 +1487,13 @@ const VisibilityObserver = { * Initializes visibility observer */ init() { - const observer = new MutationObserver(() => this.updateVisibility()); + // MARK: Mark + // const observer = new MutationObserver(() => this.updateVisibility()); + let debounceTimer = null; + const observer = new MutationObserver(() => { + if (debounceTimer) clearTimeout(debounceTimer); + debounceTimer = setTimeout(() => this.updateVisibility(), 250); + }); observer.observe(document.body, { childList: true, subtree: true }); document.body.addEventListener("click", () => this.updateVisibility()); @@ -1700,6 +1716,7 @@ const SlideCreator = { const iframe = event.target.getIframe(); if (iframe) { iframe.setAttribute('tabindex', '-1'); + iframe.setAttribute('inert', ''); } // Store start/end time and videoId for later use @@ -2772,8 +2789,26 @@ const SlideshowManager = { const currentSlide = document.querySelector(`.slide[data-item-id="${currentItemId}"]`); if (!currentSlide) return; - // Use playCurrentVideo to properly restore video with correct mute state - this.playCurrentVideo(currentSlide, currentItemId); + // YouTube player: just resume, don't reload + const ytPlayer = STATE.slideshow.videoPlayers?.[currentItemId]; + if (ytPlayer && typeof ytPlayer.playVideo === 'function') { + if (STATE.slideshow.isMuted) { + if (typeof ytPlayer.mute === 'function') ytPlayer.mute(); + } else { + if (typeof ytPlayer.unMute === 'function') ytPlayer.unMute(); + if (typeof ytPlayer.setVolume === 'function') ytPlayer.setVolume(40); + } + ytPlayer.playVideo(); + return; + } + + // HTML5 video: just resume, don't reset currentTime + const html5Video = currentSlide.querySelector('video.video-backdrop'); + if (html5Video) { + html5Video.muted = STATE.slideshow.isMuted; + if (!STATE.slideshow.isMuted) html5Video.volume = 0.4; + html5Video.play().catch(e => console.warn("Error resuming HTML5 video:", e)); + } }, /**