From 4a8be395ca5bf7d57ade5169a9a9f14af38748ba Mon Sep 17 00:00:00 2001 From: Trevor Mears Date: Sun, 18 Jan 2026 18:48:58 -0800 Subject: [PATCH] fix: mobile epg programme alignment --- public/css/main.css | 22 +++++++++------ public/js/components/EpgGuide.js | 47 ++++++++++++++++++++------------ 2 files changed, 43 insertions(+), 26 deletions(-) diff --git a/public/css/main.css b/public/css/main.css index 7774cd2..c00fc0d 100644 --- a/public/css/main.css +++ b/public/css/main.css @@ -989,10 +989,22 @@ video::cue { .epg-time-header { display: flex; + position: sticky; top: 0; background: var(--color-bg-secondary); z-index: 10; - margin-left: var(--epg-sidebar-width); +} + +.epg-header-corner { + width: var(--epg-sidebar-width); + flex-shrink: 0; + background: var(--color-bg-secondary); + border-right: 1px solid var(--color-border); +} + +.epg-time-slots { + display: flex; + flex: 1; } .epg-time-slot { @@ -2045,14 +2057,6 @@ kbd { width: var(--epg-sidebar-width); } - .epg-time-header { - margin-left: var(--epg-sidebar-width); - } - - .epg-time-slot { - min-width: 160px; - } - /* Movies & Series */ .movies-header, .series-header { diff --git a/public/js/components/EpgGuide.js b/public/js/components/EpgGuide.js index 3171a37..7edc032 100644 --- a/public/js/components/EpgGuide.js +++ b/public/js/components/EpgGuide.js @@ -429,17 +429,20 @@ class EpgGuide { // Calculate total height for virtual scrolling const totalHeight = this.filteredChannels.length * this.rowHeight; - // Build HTML structure with virtual scroll container + // Build HTML structure - header is INSIDE scroll container for natural sync this.container.innerHTML = `
-
- ${timeSlots.map(slot => ` -
- ${slot.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })} -
- `).join('')} -
+
+
+
+ ${timeSlots.map(slot => ` +
+ ${slot.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })} +
+ `).join('')} +
+
@@ -465,28 +468,38 @@ class EpgGuide { this.scrollContainer?.removeEventListener('scroll', this._hScrollHandler); } - // Get reference to time header for horizontal scroll sync - this.timeHeader = this.container.querySelector('.epg-time-header'); + // Get reference to time slots container for horizontal scroll sync + this.timeSlotsContainer = this.container.querySelector('.epg-time-slots'); // 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); + // No need for horizontal scroll sync anymore - header is inside scroll container // Initial render of visible rows this.updateVisibleRows(); + // Sync header corner width with actual sidebar width (handles CSS overrides) + this.syncHeaderCornerWidth(); + // Add now indicator this.updateNowIndicator(); } + /** + * Sync header corner width with actual sidebar width + * This handles cases where CSS variables are overridden on mobile + */ + syncHeaderCornerWidth() { + const sidebar = this.container.querySelector('.epg-channel-info'); + const headerCorner = this.container.querySelector('.epg-header-corner'); + if (sidebar && headerCorner) { + const actualWidth = sidebar.offsetWidth; + headerCorner.style.width = `${actualWidth}px`; + } + } + /** * Update visible rows based on scroll position (Virtual Scrolling) */