This commit is contained in:
Filipinos 2025-07-28 15:29:50 +02:00
parent 44e9d78b08
commit 9acd8a1b58
3 changed files with 53 additions and 58 deletions

View File

@ -463,7 +463,6 @@ body.light-theme::-webkit-scrollbar-thumb:hover, body.light-theme .item-details:
==============================================
*/
/* Styles to manage hero loading state and content section visibility */
.hero.loading .hero-content {
opacity: 0;
}
@ -472,9 +471,8 @@ body.light-theme::-webkit-scrollbar-thumb:hover, body.light-theme .item-details:
opacity: 1;
}
/* Custom styles for settings modal descriptions */
#settingsModal .text-muted {
color: var(--text-primary); /* MODIFIED: Replaced 'white !important' for theme consistency */
color: var(--text-primary);
}
#main-view {
@ -904,8 +902,10 @@ body.sidebar-collapsed #main-container {
.item-poster {
display: block;
width: 100%;
height: 0;
padding-bottom: 150%;
height: auto;
aspect-ratio: 2 / 3;
object-fit: cover;
background-color: var(--secondary);
background-size: cover;
background-position: center;
transition: transform 0.6s cubic-bezier(0.23, 1, 0.32, 1);
@ -915,12 +915,6 @@ body.sidebar-collapsed #main-container {
transform: scale(1.08);
}
.item-poster img {
display: block;
width: 100%;
height: auto;
}
.item-overlay {
position: absolute;
top: 0;
@ -3043,9 +3037,8 @@ body.miniplayer-active #musicPlayerContainer {
#volumeSlider {
-webkit-appearance: none;
appearance: none;
/* Removed writing-mode: bt-lr; */
width: 100px; /* Adjusted for horizontal orientation */
height: 8px; /* Adjusted for horizontal orientation */
width: 100px;
height: 8px;
background: var(--glass);
border-radius: 4px;
}
@ -3408,8 +3401,6 @@ body.miniplayer-active { padding-bottom: 85px; }
/* --- m3u-generator.css --- */
/* M3U Generator Section */
.m3u-animated-item {
opacity: 0;
transform: translateY(20px);
@ -3516,7 +3507,7 @@ body.miniplayer-active { padding-bottom: 85px; }
margin-right: 0.8rem;
background-color: var(--secondary);
border: 1px solid var(--glass-border);
flex-shrink: 0; /* Prevent shrinking */
flex-shrink: 0;
}
#m3u-libraries-container .form-check-label {
@ -3524,7 +3515,7 @@ body.miniplayer-active { padding-bottom: 85px; }
cursor: pointer;
color: var(--text-secondary);
font-size: 0.9rem;
line-height: 1.2; /* Ensure consistent line height */
line-height: 1.2;
}
#m3u-libraries-container .form-check-input:checked {
@ -3559,7 +3550,7 @@ body.miniplayer-active { padding-bottom: 85px; }
font-family: 'Orbitron', sans-serif;
font-size: 1.4rem;
margin-bottom: 1.5rem;
color: white; /* Changed to white for better visibility */
color: white;
}
.m3u-instructions {
@ -3579,19 +3570,18 @@ body.miniplayer-active { padding-bottom: 85px; }
padding: 1rem;
font-size: 1rem;
border-radius: var(--border-radius-md);
transition: all 0.3s ease; /* Added for animation */
transition: all 0.3s ease;
}
#download-m3u-btn:hover {
transform: translateY(-3px); /* Added for hover effect */
box-shadow: var(--shadow-lg); /* Added for hover effect */
transform: translateY(-3px);
box-shadow: var(--shadow-lg);
}
#download-m3u-btn span {
margin-left: 0.5rem;
}
/* Loading state for libraries */
#m3u-libraries-loader {
display: flex;
flex-direction: column;
@ -3607,7 +3597,6 @@ body.miniplayer-active { padding-bottom: 85px; }
margin-bottom: 1rem;
}
/* Light Theme */
.light-theme .m3u-config-panel {
background: var(--secondary);
}
@ -3638,7 +3627,6 @@ body.miniplayer-active { padding-bottom: 85px; }
color: var(--accent-dark);
}
/* Responsive */
@media (max-width: 992px) {
.m3u-container {
grid-template-columns: 1fr;
@ -3920,4 +3908,4 @@ body.miniplayer-active { padding-bottom: 85px; }
.provider-card:hover .provider-tooltip {
opacity: 1;
transform: translateY(0);
}
}

View File

@ -29,6 +29,7 @@ export const state = {
localSeries: [],
localArtists: [],
localPhotos: [],
localContentLookup: new Set(),
db: null,
lastScrollPosition: 0,
currentItemId: null,

View File

@ -64,6 +64,29 @@ export async function loadLocalContent() {
state.jellyfinMovies = jfMovies;
state.jellyfinSeries = jfSeries;
state.localContentLookup.clear();
const normalize = (str) => str ? str.toLowerCase().trim().replace(/\s+/g, ' ') : '';
const processSource = (source) => {
if (!Array.isArray(source)) return;
source.forEach(server => {
if (server && Array.isArray(server.titulos)) {
server.titulos.forEach(t => {
if (t && t.title) {
const year = t.year ? String(t.year).slice(0, 4) : 'any';
const lookupKey = `${normalize(t.title)}|${year}`;
state.localContentLookup.add(lookupKey);
}
});
}
});
};
processSource(state.localMovies);
processSource(state.localSeries);
processSource(state.jellyfinMovies);
processSource(state.jellyfinSeries);
} catch (error) {
showNotification(_("errorLoadingLocalContent"), "error");
}
@ -79,7 +102,6 @@ export function resetView() {
const heroBg1 = document.querySelector('.hero-background-1');
const heroBg2 = document.querySelector('.hero-background-2');
// Hide all main content sections
if (mainContent) {
mainContent.style.display = 'none';
}
@ -93,12 +115,10 @@ export function resetView() {
document.getElementById('providers-section').style.display = 'none';
document.getElementById('m3u-generator-section').style.display = 'none';
// Show hero if enabled
if (heroSection) {
if (state.settings.showHero) {
heroSection.style.display = 'flex';
// Clear dynamic hero content and reset to default
if (state.heroIntervalId) {
clearInterval(state.heroIntervalId);
state.heroIntervalId = null;
@ -148,7 +168,7 @@ export function switchView(viewType) {
}
if (mainContent) {
mainContent.style.display = 'block'; // Ensure main content is visible when switching views
mainContent.style.display = 'block';
}
const sidebar = document.getElementById('sidebar-nav');
@ -182,7 +202,6 @@ export function switchView(viewType) {
if (el) el.style.display = 'none';
});
// Explicitly reset the Providers section to its initial state before view switch
const providersSection = document.getElementById('providers-section');
if (providersSection) {
const detailsContainer = document.getElementById('provider-details-container');
@ -271,7 +290,6 @@ export function switchView(viewType) {
loadProviders();
break;
case 'm3u-generator':
// The m3u-generator.js file handles its own initialization
break;
}
@ -453,31 +471,22 @@ function isContentAvailableLocally(title, type, year) {
const normalize = (str) => str.toLowerCase().trim().replace(/\s+/g, ' ');
const normalizedTitle = normalize(title);
const yearKey = year ? String(year).slice(0, 4) : 'any';
const checkSource = (source, itemType) => {
if (!Array.isArray(source)) return false;
return source.some(server =>
server && Array.isArray(server.titulos) &&
server.titulos.some(t => {
if (!t || typeof t.title !== 'string') return false;
const localTitle = normalize(t.title);
if (localTitle !== normalizedTitle) return false;
if (year && t.year && Math.abs(parseInt(t.year) - parseInt(year)) > 1) return false;
if (itemType && t.type && t.type.toLowerCase() !== itemType.toLowerCase()) return false;
return true;
})
);
};
if (checkSource(state.localMovies, 'movie')) return true;
if (checkSource(state.localSeries, 'series')) return true;
if (checkSource(state.jellyfinMovies, 'movie')) return true;
if (checkSource(state.jellyfinSeries, 'series')) return true;
const lookupKey = `${normalizedTitle}|${yearKey}`;
if (state.localContentLookup.has(lookupKey)) {
return true;
}
const lookupKeyAnyYear = `${normalizedTitle}|any`;
if (yearKey !== 'any' && state.localContentLookup.has(lookupKeyAnyYear)) {
return true;
}
return false;
}
export function renderGrid(items, append = false, gridId = 'content-grid') {
const grid = document.getElementById(gridId);
if (!append) grid.innerHTML = '';
@ -513,7 +522,7 @@ export function renderGrid(items, append = false, gridId = 'content-grid') {
card.dataset.id = item.id;
card.dataset.type = itemType;
card.innerHTML = `
<div class="item-poster" style="background-image: url('${posterPath}')"></div>
<img src="${posterPath}" class="item-poster" loading="lazy" alt="${title}">
${voteAvg >= 7.8 ? '<span class="badge top-badge">TOP</span>' : ''}
${isAvailable ? `<span class="badge available-badge"><i class="fas fa-check-circle"></i> ${_('local')}</span>` : ''}
<div class="item-overlay">
@ -1274,7 +1283,6 @@ export async function initializeHeroSection() {
const heroSection = document.getElementById('hero-section');
if (heroSection.style.display === 'none' || !state.settings.showHero) return;
// Clear existing timers for slide changes and initial load
if (state.heroIntervalId) {
clearInterval(state.heroIntervalId);
state.heroIntervalId = null;
@ -1289,7 +1297,6 @@ export async function initializeHeroSection() {
const content = document.querySelector('.hero-content');
const heroButtons = content.querySelector('.hero-buttons');
// Set static background and show default content
content.querySelector('.hero-title').textContent = _('heroWelcome');
content.querySelector('.hero-subtitle').textContent = _('heroSubtitle');
content.querySelector('#hero-rating').innerHTML = '';
@ -1303,7 +1310,6 @@ export async function initializeHeroSection() {
gsap.set(content, { autoAlpha: 1 });
heroSection.classList.remove('loading');
// After 5 seconds, load the dynamic content if we are still on the home view
state.heroLoadTimeoutId = setTimeout(() => {
if (state.currentView === 'home') {
loadTmdbHeroContent();
@ -1318,7 +1324,7 @@ export async function initializeHeroSection() {
const popularItems = data.results.filter(i => i.backdrop_path && i.overview).slice(0, 8);
if (popularItems.length === 0) {
return; // Keep static image if no items
return;
}
let currentBg = bg1;
@ -1966,4 +1972,4 @@ export function showPrevPhoto() {
export async function loadProviders() {
const providers = await fetchAllProviders(state.settings.watchRegion);
renderProviders(providers);
}
}