diff --git a/Jellyfin.Plugin.MediaBarEnhanced/Jellyfin.Plugin.MediaBarEnhanced.csproj b/Jellyfin.Plugin.MediaBarEnhanced/Jellyfin.Plugin.MediaBarEnhanced.csproj index 9ef30a3..4f86364 100644 --- a/Jellyfin.Plugin.MediaBarEnhanced/Jellyfin.Plugin.MediaBarEnhanced.csproj +++ b/Jellyfin.Plugin.MediaBarEnhanced/Jellyfin.Plugin.MediaBarEnhanced.csproj @@ -12,7 +12,7 @@ Jellyfin Media Bar Enhanced Plugin CodeDevMLH - 1.5.0.24 + 1.5.0.25 https://github.com/CodeDevMLH/jellyfin-plugin-media-bar-enhanced diff --git a/Jellyfin.Plugin.MediaBarEnhanced/Web/mediaBarEnhanced.css b/Jellyfin.Plugin.MediaBarEnhanced/Web/mediaBarEnhanced.css index d8b877a..3df7c39 100644 --- a/Jellyfin.Plugin.MediaBarEnhanced/Web/mediaBarEnhanced.css +++ b/Jellyfin.Plugin.MediaBarEnhanced/Web/mediaBarEnhanced.css @@ -991,4 +991,9 @@ .dots-container .slide-counter { margin: 0; +} + +/* Fix scrolling issue in TV mode - preserve space for slideshow */ +.layout-tv html, .layout-tv body { + scroll-padding-top: 65vh; } \ No newline at end of file diff --git a/Jellyfin.Plugin.MediaBarEnhanced/Web/mediaBarEnhanced.js b/Jellyfin.Plugin.MediaBarEnhanced/Web/mediaBarEnhanced.js index c299323..a355485 100644 --- a/Jellyfin.Plugin.MediaBarEnhanced/Web/mediaBarEnhanced.js +++ b/Jellyfin.Plugin.MediaBarEnhanced/Web/mediaBarEnhanced.js @@ -2705,62 +2705,75 @@ const SlideshowManager = { } const activeElement = document.activeElement; - // Check if we're in TV mode (checking class on html or body is more reliable) - const isTvMode = document.documentElement.classList.contains('layout-tv') || document.body.classList.contains('layout-tv') || (window.layoutManager && window.layoutManager.tv); - const isSlideshowFocused = container.contains(activeElement) || activeElement === container || (!isTvMode && activeElement === document.body); - - const isInputElement = activeElement && (activeElement.tagName === 'INPUT' || activeElement.tagName === 'TEXTAREA' || activeElement.isContentEditable); - - if (isInputElement) { - return; - } + const isTvDevice = window.browser && window.browser.tv; + const isTvLayout = window.layoutManager && window.layoutManager.tv; + const hasTvClass = document.documentElement.classList.contains('layout-tv') || document.body.classList.contains('layout-tv'); + const isTvMode = isTvDevice || isTvLayout || hasTvClass; - // Check if video player is open + // Check Focus State + const isBodyFocused = activeElement === document.body; + const hasDirectFocus = container.contains(activeElement) || activeElement === container; + + // Determine if we should handle navigation keys (Arrows, Space, M) + // TV Mode: Strict focus required (must be on slideshow) + // Desktop Mode: Loose focus allowed (slideshow OR body/nothing focused) + const canControlSlideshow = isTvMode ? hasDirectFocus : (hasDirectFocus || isBodyFocused); + + // Check for Input Fields (always ignore typing) + const isInputElement = activeElement && (activeElement.tagName === 'INPUT' || activeElement.tagName === 'TEXTAREA' || activeElement.isContentEditable); + if (isInputElement) return; + + // Check active video players (ignore if video is playing/overlay is open) const videoPlayer = document.querySelector('.videoPlayerContainer'); const trailerPlayer = document.querySelector('.youtubePlayerContainer'); - if ((videoPlayer && !videoPlayer.classList.contains('hide')) || (trailerPlayer && !trailerPlayer.classList.contains('hide'))) { - return; - } + const isVideoOpen = (videoPlayer && !videoPlayer.classList.contains('hide')) || (trailerPlayer && !trailerPlayer.classList.contains('hide')); + if (isVideoOpen) return; switch (e.key) { case "ArrowRight": - if (isTvMode && !isSlideshowFocused) return; - SlideshowManager.nextSlide(); - e.preventDefault(); + if (canControlSlideshow) { + SlideshowManager.nextSlide(); + e.preventDefault(); + } break; case "ArrowLeft": - if (isTvMode && !isSlideshowFocused) return; - SlideshowManager.prevSlide(); - e.preventDefault(); + if (canControlSlideshow) { + SlideshowManager.prevSlide(); + e.preventDefault(); + } break; case " ": // Space bar - if (isTvMode && !isSlideshowFocused) return; - this.togglePause(); - e.preventDefault(); + if (canControlSlideshow) { + this.togglePause(); + e.preventDefault(); + } break; case "m": // Mute toggle case "M": - if (isTvMode && !isSlideshowFocused) return; - this.toggleMute(); - e.preventDefault(); + if (canControlSlideshow) { + this.toggleMute(); + e.preventDefault(); + } break; case "Enter": - if (!isSlideshowFocused) return; - const currentItemId = STATE.slideshow.itemIds[STATE.slideshow.currentSlideIndex]; - if (currentItemId) { - if (window.Emby && window.Emby.Page) { - Emby.Page.show( - `/details?id=${currentItemId}&serverId=${STATE.jellyfinData.serverId}` - ); - } else { - window.location.href = `#/details?id=${currentItemId}&serverId=${STATE.jellyfinData.serverId}`; - } + // Enter always requires direct focus on the slideshow to avoid conflicts + if (hasDirectFocus) { + const currentItemId = STATE.slideshow.itemIds[STATE.slideshow.currentSlideIndex]; + if (currentItemId) { + if (window.Emby && window.Emby.Page) { + Emby.Page.show( + `/details?id=${currentItemId}&serverId=${STATE.jellyfinData.serverId}` + ); + } else { + window.location.href = `#/details?id=${currentItemId}&serverId=${STATE.jellyfinData.serverId}`; + } + } + e.preventDefault(); } - e.preventDefault(); break; } }); diff --git a/manifest.json b/manifest.json index 2afba1e..820d182 100644 --- a/manifest.json +++ b/manifest.json @@ -9,7 +9,7 @@ "imageUrl": "https://git.mahom03-spacecloud.de/CodeDevMLH/jellyfin-plugin-media-bar-enhanced/raw/branch/main/logo.png", "versions": [ { - "version": "1.5.0.24", + "version": "1.5.0.25", "changelog": "- fix: Keyboard controls in TV mode\n- Add sorting options for content\n- Update mediaBarEnhanced.js and mediaBarEnhanced.css with version 4.0.1 from original repo", "targetAbi": "10.11.0.0", "sourceUrl": "https://git.mahom03-spacecloud.de/CodeDevMLH/jellyfin-plugin-media-bar-enhanced/releases/download/v1.5.0.24/Jellyfin.Plugin.MediaBarEnhanced.zip",