diff --git a/frontend/src/pages/Guide.jsx b/frontend/src/pages/Guide.jsx
index eae1c2a7..cfc1d298 100644
--- a/frontend/src/pages/Guide.jsx
+++ b/frontend/src/pages/Guide.jsx
@@ -492,7 +492,6 @@ export default function TVChannelGuide({ startDate, endDate }) {
guideRef.current.scrollLeft = scrollPosition;
}
};
-
// Renders each program block
function renderProgram(program, channelStart) {
const programKey = `${program.tvg_id}-${program.start_time}`;
@@ -522,18 +521,9 @@ export default function TVChannelGuide({ startDate, endDate }) {
const isLive = now.isAfter(programStart) && now.isBefore(programEnd);
// Determine if the program has ended
- const isPast = now.isAfter(programEnd);
-
- // Check if this program is expanded
+ const isPast = now.isAfter(programEnd); // Check if this program is expanded
const isExpanded = expandedProgramId === program.id;
- // Calculate how much of the program is cut off
- const cutOffMinutes = Math.max(
- 0,
- channelStart.diff(programStart, 'minute')
- );
- const cutOffPx = (cutOffMinutes / MINUTE_INCREMENT) * MINUTE_BLOCK_WIDTH;
-
// Set the height based on expanded state
const rowHeight = isExpanded ? EXPANDED_PROGRAM_HEIGHT : PROGRAM_HEIGHT;
@@ -542,6 +532,25 @@ export default function TVChannelGuide({ startDate, endDate }) {
const MIN_EXPANDED_WIDTH = 450; // Minimum width in pixels when expanded
const expandedWidthPx = Math.max(widthPx, MIN_EXPANDED_WIDTH);
+ // Calculate text positioning for long programs that start before the visible area
+ const currentScrollLeft = guideRef.current?.scrollLeft || 0;
+ const programStartInView = leftPx + gapSize;
+ const programEndInView = leftPx + gapSize + widthPx;
+ const viewportLeft = currentScrollLeft;
+
+ // Check if program starts before viewport but extends into it
+ const startsBeforeView = programStartInView < viewportLeft;
+ const extendsIntoView = programEndInView > viewportLeft;
+
+ // Calculate text offset to position it at the visible portion
+ let textOffsetLeft = 0;
+ if (startsBeforeView && extendsIntoView) {
+ // Position text at the start of the visible area, but not beyond the program end
+ const visibleStart = Math.max(viewportLeft - programStartInView, 0);
+ const maxOffset = widthPx - 200; // Leave some space for text, don't push to very end
+ textOffsetLeft = Math.min(visibleStart, maxOffset);
+ }
+
return (
-
+
{programStart.format('h:mma')} - {programEnd.format('h:mma')}
-
-
- {/* Description is always shown but expands when row is expanded */}
+ {/* Description is always shown but expands when row is expanded */}
{program.description && (
-
- {program.description}
-
+
+ {program.description}
+
+
)}
{/* Expanded content */}
@@ -906,101 +925,100 @@ export default function TVChannelGuide({ startDate, endDate }) {
borderBottom: '1px solid #27272A',
width: hourTimeline.length * HOUR_WIDTH,
}}
- >
- {hourTimeline.map((hourData, hourIndex) => {
- const { time, isNewDay, dayLabel } = hourData;
+ > {hourTimeline.map((hourData) => {
+ const { time, isNewDay } = hourData;
- return (
- handleTimeClick(time, e)}
+ >
+ {/* Remove the special day label for new days since we'll show day for all hours */}
+
+ {/* Position time label at the left border of each hour block */}
+ handleTimeClick(time, e)}
>
- {/* Remove the special day label for new days since we'll show day for all hours */}
-
- {/* Position time label at the left border of each hour block */}
+ {/* Show day above time for every hour using the same format */}
- {/* Show day above time for every hour using the same format */}
-
- {formatDayLabel(time)}{' '}
- {/* Use same formatDayLabel function for all hours */}
-
- {time.format('h:mm')}
-
- {time.format('A')}
-
+ {formatDayLabel(time)}{' '}
+ {/* Use same formatDayLabel function for all hours */}
+ {time.format('h:mm')}
+
+ {time.format('A')}
+
+
- {/* Hour boundary marker - more visible */}
-
+ {/* Hour boundary marker - more visible */}
+
- {/* Quarter hour tick marks */}
-
- {[15, 30, 45].map((minute) => (
-
- ))}
-
+ {/* Quarter hour tick marks */}
+
+ {[15, 30, 45].map((minute) => (
+
+ ))}
- );
- })}
+
+ );
+ })}