From 066ad6fc844297ecd29d7bc28fac2cb2aa2a07bc Mon Sep 17 00:00:00 2001 From: CodeDevMLH <145071728+CodeDevMLH@users.noreply.github.com> Date: Tue, 24 Feb 2026 19:19:38 +0100 Subject: [PATCH] Add Eid feature: create CSS and JS for Eid symbols and animations --- Jellyfin.Plugin.Seasonals/Web/eid.css | 53 ++++++++++++++++ Jellyfin.Plugin.Seasonals/Web/eid.js | 87 +++++++++++++++++++++++++++ 2 files changed, 140 insertions(+) create mode 100644 Jellyfin.Plugin.Seasonals/Web/eid.css create mode 100644 Jellyfin.Plugin.Seasonals/Web/eid.js diff --git a/Jellyfin.Plugin.Seasonals/Web/eid.css b/Jellyfin.Plugin.Seasonals/Web/eid.css new file mode 100644 index 0000000..43cc54d --- /dev/null +++ b/Jellyfin.Plugin.Seasonals/Web/eid.css @@ -0,0 +1,53 @@ +.eid-container { + display: block; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + pointer-events: none; + z-index: 10; + contain: strict; + overflow: hidden; +} + +.eid-symbol { + position: absolute; + user-select: none; + font-size: 1.5em; +} + +.eid-symbol.floating-star { + opacity: 0; + animation: eid-twinkle 4s ease-in-out infinite; + mix-blend-mode: screen; +} + +.lantern-rope { + position: absolute; + top: 0; + width: 2px; + background: linear-gradient(to bottom, rgba(255, 215, 0, 0.1), rgba(255, 215, 0, 0.6)); + transform-origin: top center; + animation: lantern-swing 4s ease-in-out infinite alternate; +} + +.lantern-emoji { + position: absolute; + bottom: -20px; + left: 50%; + transform: translateX(-50%); + font-size: 2.5em; + filter: drop-shadow(0 0 10px rgba(255, 215, 0, 0.5)); +} + +@keyframes lantern-swing { + 0% { transform: rotate(-8deg); } + 100% { transform: rotate(8deg); } +} + +@keyframes eid-twinkle { + 0% { transform: scale(0.8); opacity: 0; text-shadow: 0 0 5px gold; } + 50% { transform: scale(1.2); opacity: 0.8; text-shadow: 0 0 20px gold; } + 100% { transform: scale(0.8); opacity: 0; text-shadow: 0 0 5px gold; } +} diff --git a/Jellyfin.Plugin.Seasonals/Web/eid.js b/Jellyfin.Plugin.Seasonals/Web/eid.js new file mode 100644 index 0000000..2c3f463 --- /dev/null +++ b/Jellyfin.Plugin.Seasonals/Web/eid.js @@ -0,0 +1,87 @@ +const config = window.SeasonalsPluginConfig?.Eid || {}; +const eid = config.EnableEid !== undefined ? config.EnableEid : true; + +const eidSymbols = ['🌙', '⭐', '✨']; + +let msgPrinted = false; + +function toggleEid() { + const container = document.querySelector('.eid-container'); + if (!container) return; + + const videoPlayer = document.querySelector('.videoPlayerContainer'); + const trailerPlayer = document.querySelector('.youtubePlayerContainer'); + const isDashboard = document.body.classList.contains('dashboardDocument'); + const hasUserMenu = document.querySelector('#app-user-menu'); + + if (videoPlayer || trailerPlayer || isDashboard || hasUserMenu) { + container.style.display = 'none'; + if (!msgPrinted) { + console.log('Eid hidden'); + msgPrinted = true; + } + } else { + container.style.display = 'block'; + if (msgPrinted) { + console.log('Eid visible'); + msgPrinted = false; + } + } +} + +const observer = new MutationObserver(toggleEid); +observer.observe(document.body, { + childList: true, + subtree: true, + attributes: true +}); + + +function createEid(container) { + for (let i = 0; i < 25; i++) { + const symbol = document.createElement('div'); + symbol.className = 'eid-symbol'; + const isLantern = Math.random() > 0.8; + + if (isLantern) { + symbol.classList.add('lantern-rope'); + symbol.style.left = `${Math.random() * 90 + 5}%`; + symbol.style.animationDelay = `${Math.random() * -4}s`; + const ropeLen = 15 + Math.random() * 15; // 15vh to 30vh + symbol.style.height = `${ropeLen}vh`; + + const lanternSpan = document.createElement('span'); + lanternSpan.className = 'lantern-emoji'; + lanternSpan.textContent = '🏮'; + symbol.appendChild(lanternSpan); + } else { + symbol.textContent = eidSymbols[Math.floor(Math.random() * eidSymbols.length)]; + symbol.classList.add('floating-star'); + symbol.style.left = `${Math.random() * 100}%`; + symbol.style.top = `${Math.random() * 100}%`; + symbol.style.animationDelay = `${Math.random() * -5}s`; + } + + symbol.addEventListener('animationiteration', () => { + if (!isLantern) { + symbol.style.left = `${Math.random() * 90 + 5}%`; + symbol.style.top = `${Math.random() * 100}%`; + } + }); + + container.appendChild(symbol); + } +} + +function initializeEid() { + if (!eid) return; + const container = document.querySelector('.eid-container') || document.createElement("div"); + if (!document.querySelector('.eid-container')) { + container.className = "eid-container"; + container.setAttribute("aria-hidden", "true"); + document.body.appendChild(container); + } + createEid(container); + toggleEid(); +} +initializeEid();