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

View File

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

View File

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