initial commit 2

This commit is contained in:
2026-04-02 18:33:07 -07:00
parent fcf67bee82
commit 5883a664d0
3 changed files with 181 additions and 0 deletions

120
banner.js Normal file
View File

@@ -0,0 +1,120 @@
(function () {
// =========== README ==========
// Update the message below
// incrementversion DISMISSED_KEY
const DISMISSED_KEY = 'jf-banner-dismissed-v1';
const BANNER_ID = 'custom-announcement-banner';
// Edit these to change banner content:
const BANNER_HTML = `
<span class="banner-text">
<strong>News:</strong>
<a href="https://jellyfin.org/downloads/clients/" target="_blank" rel="noopener">
Get the official app for your device
</a>
|
<a href="https://google.com/" target="_blank" rel="noopener">
Submit requests
</a>
</span>
<button id="custom-banner-close" aria-label="Dismiss banner">&#x2715;</button>
`;
const BANNER_CSS = `
#custom-announcement-banner {
position: fixed;
top: 0;
left: 0;
display: flex;
align-items: center;
justify-content: space-between;
background: #1c3a5c;
color: #e0e0e0;
font-size: 0.9em;
padding: 8px 16px;
box-sizing: border-box;
width: 100%;
z-index: 9999;
border-bottom: 1px solid #2d5a8e;
}
#custom-announcement-banner a {
color: #7cb8f0;
}
#custom-banner-close {
background: none;
border: none;
color: #e0e0e0;
cursor: pointer;
font-size: 1.1em;
padding: 0 4px;
flex-shrink: 0;
}
`;
function applyOffset() {
const banner = document.getElementById(BANNER_ID);
const offset = banner ? (banner.offsetHeight + 'px') : '';
const header = document.querySelector('.headerTop');
const drawer = document.querySelector('.mainDrawer');
const sections = document.querySelector('.homeSectionsContainer');
if (header) header.style.marginTop = offset;
if (drawer) drawer.style.marginTop = offset;
if (sections) sections.style.marginTop = offset;
}
function isHomePage() {
const h = window.location.hash;
return h === '' || h === '#' || h === '#/home' || h === '#!'
|| h === '#!/' || h.startsWith('#/home') || h.startsWith('#!/home');
}
function injectBanner() {
if (document.getElementById(BANNER_ID)) return;
const banner = document.createElement('div');
banner.id = BANNER_ID;
banner.innerHTML = BANNER_HTML;
document.body.insertBefore(banner, document.body.firstChild);
document.getElementById('custom-banner-close').addEventListener('click', function () {
sessionStorage.setItem(DISMISSED_KEY, '1');
document.getElementById(BANNER_ID).remove();
applyOffset();
});
applyOffset();
}
function removeBanner() {
const el = document.getElementById(BANNER_ID);
if (el) el.remove();
applyOffset();
}
function update() {
if (sessionStorage.getItem(DISMISSED_KEY)) { removeBanner(); return; }
if (isHomePage()) { injectBanner(); } else { removeBanner(); }
}
// Inject CSS once
const style = document.createElement('style');
style.textContent = BANNER_CSS;
document.head.appendChild(style);
// React to SPA navigation
window.addEventListener('hashchange', update);
// Watch for Jellyfin's deferred body rendering (SPA bootstraps after DOMContentLoaded)
// subtree: true catches .headerTop wherever it appears in the DOM
const observer = new MutationObserver(function () {
update();
applyOffset();
});
document.addEventListener('DOMContentLoaded', function () {
observer.observe(document.body, { childList: true, subtree: true });
update();
});
// Fallback: run immediately if DOMContentLoaded already fired
if (document.readyState !== 'loading') update();
})();