@@ -165,22 +165,28 @@ export const addOrRemoveNotification = async (programDetails) => {
165165 }
166166 }
167167
168- // FIX for RangeError: Invalid time value
168+ // --- ** FIX 1: Robust lead time calculation** ---
169169 // Ensure notificationLeadTime is a valid number, default to 10 if not.
170- const notificationLeadTime = parseInt ( guideState . settings . notificationLeadTime , 10 ) || 10 ;
170+ const notificationLeadTime = parseInt ( guideState . settings . notificationLeadTime , 10 ) ;
171+ if ( isNaN ( notificationLeadTime ) ) {
172+ console . warn ( `[NOTIF] Invalid 'notificationLeadTime' in settings: ${ guideState . settings . notificationLeadTime } . Defaulting to 10.` ) ;
173+ notificationLeadTime = 10 ;
174+ }
175+
171176 console . log ( '[NOTIF_DEBUG] Program Start:' , programDetails . programStart ) ;
172177 console . log ( '[NOTIF_DEBUG] Notification Lead Time (minutes):' , notificationLeadTime ) ;
173178
174179 const programStartTime = new Date ( programDetails . programStart ) ;
175- const scheduledTime = new Date ( programStartTime . getTime ( ) - notificationLeadTime * 60 * 1000 ) ;
176180
177- // Check if scheduledTime is a valid date before proceeding
178- if ( isNaN ( scheduledTime . getTime ( ) ) ) {
179- console . error ( '[NOTIF] Calculated scheduledTime is invalid. programStartTime: ' , programStartTime , 'notificationLeadTime:' , notificationLeadTime ) ;
180- showNotification ( `Could not set notification: Invalid program start time or lead time.` , true ) ;
181+ // --- **FIX 2: Validate program start time** ---
182+ if ( isNaN ( programStartTime . getTime ( ) ) ) {
183+ console . error ( '[NOTIF_ERROR] The program start time is invalid.' , programDetails . programStart ) ;
184+ showNotification ( 'Cannot set notification due to an invalid program start time.' , true ) ;
181185 return ;
182186 }
183-
187+
188+ const scheduledTime = new Date ( programStartTime . getTime ( ) - notificationLeadTime * 60 * 1000 ) ;
189+
184190 if ( scheduledTime <= new Date ( ) ) {
185191 showNotification ( `Cannot set notification for a program that has already started or passed.` , true ) ;
186192 console . warn ( '[NOTIF] Attempted to set notification for a program already in progress or past.' ) ;
@@ -196,15 +202,16 @@ export const addOrRemoveNotification = async (programDetails) => {
196202 programStop : programDetails . programStop ,
197203 programDesc : programDetails . programDesc ,
198204 programId : programDetails . programId ,
199- notificationLeadTime : notificationLeadTime , // Use the parsed value
200205 scheduledTime : scheduledTime . toISOString ( )
201206 } ;
202207
203208 const addedNotification = await addProgramNotification ( newNotificationData ) ;
204209 if ( addedNotification ) {
205- // Notify other tabs via BroadcastChannel after a successful local action
206210 notificationChannel . postMessage ( { type : 'refresh-notifications' } ) ;
207- guideState . userNotifications . push ( { ...addedNotification , status : 'pending' } ) ;
211+ // Manually add the lead time to the object for immediate correct rendering
212+ const completeNotification = { ...addedNotification , status : 'pending' , notificationLeadTime : notificationLeadTime } ;
213+ guideState . userNotifications . push ( completeNotification ) ;
214+
208215 renderNotifications ( ) ;
209216 await handleSearchAndFilter ( false ) ;
210217 showNotification ( `Notification set for "${ addedNotification . programTitle } "!` ) ;
@@ -223,8 +230,6 @@ export const addOrRemoveNotification = async (programDetails) => {
223230 * @returns {object|null } The notification object if found, otherwise null.
224231 */
225232export const findNotificationForProgram = ( program , channelId ) => {
226- // MODIFIED: Removed the `n.status === 'pending'` check to make the indicator persistent
227- // for any notification associated with this program, regardless of its status.
228233 return guideState . userNotifications . find ( n =>
229234 n . channelId === channelId &&
230235 n . programId === program . programId
@@ -240,24 +245,35 @@ export const renderNotifications = () => {
240245
241246 const now = new Date ( ) ;
242247 const upcomingNotifications = guideState . userNotifications
243- . filter ( n => new Date ( n . scheduledTime ) . getTime ( ) > now . getTime ( ) && n . status === 'pending' )
248+ . filter ( n => n . status === 'pending' && new Date ( n . scheduledTime ) . getTime ( ) > now . getTime ( ) )
244249 . sort ( ( a , b ) => new Date ( a . scheduledTime ) - new Date ( b . scheduledTime ) ) ;
245250
246251 UIElements . noNotificationsMessage . classList . toggle ( 'hidden' , upcomingNotifications . length > 0 ) ;
247252
248253 notificationListEl . innerHTML = upcomingNotifications . map ( notif => {
254+ // --- **FIX 3: Robust rendering to prevent crashes and "undefined" bug** ---
249255 const programStartTime = new Date ( notif . programStart ) ;
250256 const notificationTime = new Date ( notif . scheduledTime ) ;
251- const formattedProgramTime = programStartTime . toLocaleString ( [ ] , { weekday : 'short' , month : 'short' , day : 'numeric' , hour : '2-digit' , minute : '2-digit' } ) ;
252- const formattedNotificationTime = notificationTime . toLocaleTimeString ( [ ] , { hour : '2-digit' , minute : '2-digit' } ) ;
257+
258+ // If dates are invalid, skip rendering this item to prevent crashes.
259+ if ( isNaN ( programStartTime . getTime ( ) ) || isNaN ( notificationTime . getTime ( ) ) ) {
260+ console . error ( '[NOTIF_RENDER] Skipping notification with invalid date:' , notif ) ;
261+ return '' ;
262+ }
263+
264+ // Calculate lead time directly from timestamps for accuracy.
265+ const leadTimeMinutes = Math . round ( ( programStartTime . getTime ( ) - notificationTime . getTime ( ) ) / 60000 ) ;
266+
267+ const formattedProgramTime = programStartTime . toLocaleString ( [ ] , { weekday : 'short' , month : 'short' , day : 'numeric' , hour : '2-digit' , minute : '2-digit' , hour12 : false } ) ;
268+ const formattedNotificationTime = notificationTime . toLocaleTimeString ( [ ] , { hour : '2-digit' , minute : '2-digit' , hour12 : false } ) ;
253269
254270 return `
255271 <div class="flex items-center p-4 border-b border-gray-700/50 hover:bg-gray-800 transition-colors rounded-md" data-notification-id="${ notif . id } " data-status="${ notif . status } ">
256272 <img src="${ notif . channelLogo || 'https://placehold.co/48x48/1f2937/d1d5db?text=?;&font=Inter' } " onerror="this.onerror=null; this.src='https://placehold.co/48x48/1f2937/d1d5db?text=?';" class="w-12 h-12 object-contain mr-4 flex-shrink-0 rounded-md bg-gray-700">
257273 <div class="flex-grow">
258- <p class="font-semibold text-white text-md">${ notif . programTitle } </p>
259- <p class="text-gray-400 text-sm">${ notif . channelName } • ${ formattedProgramTime } </p>
260- <p class="text-blue-400 text-xs mt-1">Will be notified at ${ formattedNotificationTime } (${ notif . notificationLeadTime } mins before)</p>
274+ <p class="font-semibold text-white text-md">${ notif . programTitle || 'Untitled Program' } </p>
275+ <p class="text-gray-400 text-sm">${ notif . channelName || 'Unknown Channel' } • ${ formattedProgramTime } </p>
276+ <p class="text-blue-400 text-xs mt-1">Will be notified at ${ formattedNotificationTime } (${ leadTimeMinutes } mins before)</p>
261277 </div>
262278 <div class="flex items-center gap-2 flex-shrink-0 ml-4">
263279 <button class="action-btn view-program-btn p-2 rounded-full hover:bg-gray-700" title="View in TV Guide" data-channel-id="${ notif . channelId } " data-program-start="${ notif . programStart } " data-program-id="${ notif . programId } ">
@@ -292,8 +308,13 @@ export const renderPastNotifications = () => {
292308 pastNotificationsListEl . innerHTML = pastNotifications . map ( notif => {
293309 const programStartTime = new Date ( notif . programStart ) ;
294310 const notificationTriggerTime = new Date ( notif . triggeredAt || notif . notificationTime ) ;
295- const formattedProgramTime = programStartTime . toLocaleString ( [ ] , { weekday : 'short' , month : 'short' , day : 'numeric' , hour : '2-digit' , minute : '2-digit' } ) ;
296- const formattedTriggerTime = notificationTriggerTime . toLocaleTimeString ( [ ] , { hour : '2-digit' , minute : '2-digit' } ) ;
311+
312+ if ( isNaN ( programStartTime . getTime ( ) ) || isNaN ( notificationTriggerTime . getTime ( ) ) ) {
313+ return '' ;
314+ }
315+
316+ const formattedProgramTime = programStartTime . toLocaleString ( [ ] , { weekday : 'short' , month : 'short' , day : 'numeric' , hour : '2-digit' , minute : '2-digit' , hour12 : false } ) ;
317+ const formattedTriggerTime = notificationTriggerTime . toLocaleTimeString ( [ ] , { hour : '2-digit' , minute : '2-digit' , hour12 : false } ) ;
297318
298319 let statusText = '' ;
299320 if ( notif . status === 'sent' ) {
@@ -306,8 +327,8 @@ export const renderPastNotifications = () => {
306327 <div class="flex items-center p-4 border-b border-gray-700/50 hover:bg-gray-800 transition-colors rounded-md opacity-70" data-notification-id="${ notif . id } " data-status="${ notif . status } ">
307328 <img src="${ notif . channelLogo || 'https://placehold.co/48x48/1f2937/d1d5db?text=?;&font=Inter' } " onerror="this.onerror=null; this.src='https://placehold.co/48x48/1f2937/d1d5db?text=?';" class="w-12 h-12 object-contain mr-4 flex-shrink-0 rounded-md bg-gray-700">
308329 <div class="flex-grow">
309- <p class="font-semibold text-white text-md">${ notif . programTitle } </p>
310- <p class="text-gray-400 text-sm">${ notif . channelName } • ${ formattedProgramTime } </p>
330+ <p class="font-semibold text-white text-md">${ notif . programTitle || 'Untitled Program' } </p>
331+ <p class="text-gray-400 text-sm">${ notif . channelName || 'Unknown Channel' } • ${ formattedProgramTime } </p>
311332 <p class="text-xs mt-1 text-gray-500">${ statusText } </p>
312333 </div>
313334 <div class="flex items-center gap-2 flex-shrink-0 ml-4">
0 commit comments