From f9fefa39478086f070daf43faffd3eba2a077d76 Mon Sep 17 00:00:00 2001 From: Trevor Mears Date: Sun, 18 Jan 2026 17:06:26 -0800 Subject: [PATCH] fix: filter homepage recent sections by hidden status --- public/css/main.css | 84 +++++++++++++++++--- public/img/placeholder.png | Bin 259 -> 23270 bytes public/img/poster-placeholder.jpg | Bin 0 -> 47866 bytes public/index.html | 10 +-- public/js/components/EpgGuide.js | 18 ++++- public/js/components/VideoPlayer.js | 3 + public/js/pages/HomePage.js | 116 +++++++++++++++++++++++++--- public/js/pages/WatchPage.js | 11 ++- server/routes/channels.js | 14 +++- 9 files changed, 224 insertions(+), 32 deletions(-) create mode 100644 public/img/poster-placeholder.jpg diff --git a/public/css/main.css b/public/css/main.css index 64b31c3..7774cd2 100644 --- a/public/css/main.css +++ b/public/css/main.css @@ -980,7 +980,8 @@ video::cue { .epg-grid { height: calc(100vh - var(--navbar-height) - 60px); - overflow: auto; + overflow: hidden; + overflow-y: auto; padding: var(--space-md); -webkit-overflow-scrolling: touch; overscroll-behavior: contain; @@ -1887,6 +1888,7 @@ kbd { --sidebar-width: 320px; --space-lg: 16px; --space-xl: 24px; + --epg-sidebar-width: 180px; } /* Navigation - Hide text labels, show only icons */ @@ -1900,7 +1902,8 @@ kbd { gap: 0; } - .navbar-menu span:not(.nav-icon) { + /* Hide nav link text on mobile, but keep Now Playing visible */ + .navbar-menu .nav-link span:not(.nav-icon) { display: none; } @@ -2039,7 +2042,11 @@ kbd { } .epg-channel-info { - width: 180px; + width: var(--epg-sidebar-width); + } + + .epg-time-header { + margin-left: var(--epg-sidebar-width); } .epg-time-slot { @@ -4314,7 +4321,7 @@ kbd { align-items: center; gap: 8px; padding: 6px 14px; - margin-right: 16px; + margin-right: var(--space-md); background: linear-gradient(135deg, var(--color-accent) 0%, #8b5cf6 100%); border-radius: var(--radius-full); color: white; @@ -4360,13 +4367,16 @@ kbd { } } -/* Mobile responsive */ +/* Mobile responsive - show in dropdown menu */ @media (max-width: 768px) { .now-playing-indicator { - max-width: 140px; - padding: 5px 10px; - font-size: 12px; - margin-right: 8px; + width: calc(100% - 32px); + max-width: none; + margin: 0 16px var(--space-sm) 16px; + padding: 10px 16px; + font-size: 13px; + border-radius: var(--radius-md); + justify-content: center; } } @@ -4406,7 +4416,63 @@ kbd { color: var(--color-text-bright); } +/* Scroll Wrapper with Navigation Arrows */ +.scroll-wrapper { + position: relative; +} + +.scroll-arrow { + position: absolute; + top: 50%; + transform: translateY(-50%); + z-index: 10; + width: 40px; + height: 40px; + border-radius: 50%; + background: rgba(0, 0, 0, 0.7); + border: 1px solid rgba(255, 255, 255, 0.1); + color: white; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all var(--transition-fast); + backdrop-filter: blur(8px); +} + +.scroll-arrow:hover { + background: rgba(0, 0, 0, 0.9); + border-color: var(--color-accent); + transform: translateY(-50%) scale(1.1); +} + +.scroll-arrow svg { + width: 24px; + height: 24px; +} + +.scroll-arrow.scroll-left { + left: -8px; +} + +.scroll-arrow.scroll-right { + right: -8px; +} + +.scroll-arrow.hidden { + opacity: 0; + pointer-events: none; +} + +/* Hide arrows on touch devices (they can swipe) */ +@media (hover: none) { + .scroll-arrow { + display: none; + } +} + .horizontal-scroll { + display: flex; gap: 20px; overflow-x: auto; diff --git a/public/img/placeholder.png b/public/img/placeholder.png index 3f179441c6fc909cc93382585c7fa87e1890d27a..c33035c15b37fea78a42ca2e69be1efb41e4aec3 100644 GIT binary patch literal 23270 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 literal 259 zcmZ`!!3x75488X&LU!)79c3_T54-KMe~{LyVCzt+-M)Tt^g2QaFE8&U>EothU)&l6 znv`BQ#&XW*d^!7|S<5+RG=Y%ql#IZJa|ENTHt7JHRr&6BfgCsxT@r^1pbu(H|8=u< zPT;ALjchw)KSfe|0qr#k8tbTn coev_~kD^;!9G)H?i`1%T#dWCq^4d^+0iY;M%m4rY diff --git a/public/img/poster-placeholder.jpg b/public/img/poster-placeholder.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c3283e92d2abab165119726e6c653aee66ad7d0c GIT binary patch literal 47866 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 C*mUs# literal 0 HcmV?d00001 diff --git a/public/index.html b/public/index.html index 6d2542c..c45df97 100644 --- a/public/index.html +++ b/public/index.html @@ -38,12 +38,12 @@ - -

`).join('')} -
+
@@ -461,11 +461,25 @@ class EpgGuide { if (this._scrollHandler) { this.scrollContainer?.removeEventListener('scroll', this._scrollHandler); } + if (this._hScrollHandler) { + this.scrollContainer?.removeEventListener('scroll', this._hScrollHandler); + } - // Set up scroll handler for virtual scrolling + // Get reference to time header for horizontal scroll sync + this.timeHeader = this.container.querySelector('.epg-time-header'); + + // Set up scroll handler for virtual scrolling (debounced for performance) this._scrollHandler = this.debounce(() => this.updateVisibleRows(), 16); // ~60fps this.scrollContainer.addEventListener('scroll', this._scrollHandler); + // Set up horizontal scroll sync (instant, not debounced) + this._hScrollHandler = () => { + if (this.timeHeader && this.scrollContainer) { + this.timeHeader.style.transform = `translateX(-${this.scrollContainer.scrollLeft}px)`; + } + }; + this.scrollContainer.addEventListener('scroll', this._hScrollHandler); + // Initial render of visible rows this.updateVisibleRows(); diff --git a/public/js/components/VideoPlayer.js b/public/js/components/VideoPlayer.js index a0e3a5d..fdc954a 100644 --- a/public/js/components/VideoPlayer.js +++ b/public/js/components/VideoPlayer.js @@ -1251,6 +1251,9 @@ class VideoPlayer { * Stop playback */ stop() { + // Stop any running transcode session first + this.stopTranscodeSession(); + if (this.hls) { this.hls.destroy(); this.hls = null; diff --git a/public/js/pages/HomePage.js b/public/js/pages/HomePage.js index 814b280..66e255c 100644 --- a/public/js/pages/HomePage.js +++ b/public/js/pages/HomePage.js @@ -35,8 +35,16 @@ class HomePage {

Favorite Channels

-
-
Loading favorites...
+
+ +
+
Loading favorites...
+
+
@@ -44,8 +52,16 @@ class HomePage {

Continue Watching

-
-
Loading history...
+
+ +
+
Loading history...
+
+
@@ -53,8 +69,16 @@ class HomePage {

Recently Added Movies

-
-
Coming soon
+
+ +
+
Coming soon
+
+
@@ -62,15 +86,73 @@ class HomePage {

Recently Added Series

-
-
Coming soon
+
+ +
+
Coming soon
+
+
`; this.container = document.getElementById('home-content'); + + // Attach scroll arrow handlers + this.initScrollArrows(); } + initScrollArrows() { + this.container.querySelectorAll('.scroll-wrapper').forEach(wrapper => { + const scrollContainer = wrapper.querySelector('.horizontal-scroll'); + const leftBtn = wrapper.querySelector('.scroll-left'); + const rightBtn = wrapper.querySelector('.scroll-right'); + + if (!scrollContainer || !leftBtn || !rightBtn) return; + + const scrollAmount = 300; // pixels to scroll per click + + leftBtn.addEventListener('click', () => { + scrollContainer.scrollBy({ left: -scrollAmount, behavior: 'smooth' }); + }); + + rightBtn.addEventListener('click', () => { + scrollContainer.scrollBy({ left: scrollAmount, behavior: 'smooth' }); + }); + + // Update arrow visibility based on scroll position + const updateArrows = () => { + const { scrollLeft, scrollWidth, clientWidth } = scrollContainer; + leftBtn.classList.toggle('hidden', scrollLeft <= 0); + rightBtn.classList.toggle('hidden', scrollLeft + clientWidth >= scrollWidth - 5); + }; + + // Store reference for later updates + wrapper._updateArrows = updateArrows; + + scrollContainer.addEventListener('scroll', updateArrows); + // Initial check after content loads + setTimeout(updateArrows, 100); + }); + } + + /** + * Re-check scroll arrow visibility for all sections + * Call this after dynamically loading content + */ + updateScrollArrows() { + this.container?.querySelectorAll('.scroll-wrapper').forEach(wrapper => { + if (wrapper._updateArrows) { + wrapper._updateArrows(); + } + }); + } + + async loadDashboardData() { if (this.isLoading) return; this.isLoading = true; @@ -147,6 +229,9 @@ class HomePage { }); }); + // Update scroll arrows after content renders + this.updateScrollArrows(); + } catch (err) { console.error('[Dashboard] Error loading favorite channels:', err); list.innerHTML = '
Error loading favorites
'; @@ -161,7 +246,7 @@ class HomePage { return `
${name}
@@ -223,6 +308,9 @@ class HomePage { } }); }); + + // Update scroll arrows after content renders + this.updateScrollArrows(); } navigateToSeries(item) { @@ -268,6 +356,9 @@ class HomePage { if (item) this.playItem(item); }); }); + + // Update scroll arrows after content renders + this.updateScrollArrows(); } catch (err) { console.error('[Dashboard] Error loading recent movies:', err); } @@ -294,6 +385,9 @@ class HomePage { if (item) this.navigateToSeries(item); }); }); + + // Update scroll arrows after content renders + this.updateScrollArrows(); } catch (err) { console.error('[Dashboard] Error loading recent series:', err); } @@ -311,7 +405,7 @@ class HomePage { return `
- ${data.title || item.name} + ${data.title || item.name}
@@ -336,7 +430,7 @@ class HomePage { return `
- ${item.name} + ${item.name}
diff --git a/public/js/pages/WatchPage.js b/public/js/pages/WatchPage.js index 3f3041c..53061e7 100644 --- a/public/js/pages/WatchPage.js +++ b/public/js/pages/WatchPage.js @@ -888,7 +888,14 @@ class WatchPage { renderDetails() { if (!this.content) return; - this.posterEl.src = this.content.poster || '/img/placeholder.png'; + const isChannel = this.content.type === 'channel' || !this.content.type; // Default to channel if unknown + const fallback = isChannel ? '/img/placeholder.png' : '/img/poster-placeholder.jpg'; + + this.posterEl.onerror = () => { + this.posterEl.onerror = null; + this.posterEl.src = fallback; + }; + this.posterEl.src = this.content.poster || fallback; this.posterEl.alt = this.content.title || ''; this.contentTitleEl.textContent = this.content.title || ''; this.yearEl.textContent = this.content.year || ''; @@ -984,7 +991,7 @@ class WatchPage { `).join(''); diff --git a/server/routes/channels.js b/server/routes/channels.js index 4c84d3d..15965a1 100644 --- a/server/routes/channels.js +++ b/server/routes/channels.js @@ -298,9 +298,17 @@ router.get('/recent', async (req, res) => { const db = getDb(); const recentItems = db.prepare(` - SELECT * FROM playlist_items - WHERE type = ? AND is_hidden = 0 - ORDER BY added_at DESC + SELECT * FROM playlist_items p + WHERE p.type = ? + AND p.is_hidden = 0 + AND NOT EXISTS ( + SELECT 1 FROM categories c + WHERE c.source_id = p.source_id + AND c.category_id = p.category_id + AND c.type = p.type + AND c.is_hidden = 1 + ) + ORDER BY p.added_at DESC LIMIT ? `).all(type, parseInt(limit));