diff --git a/package.json b/package.json index e83d8d0..d455137 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "my-weekly-todo-list", - "version": "1.75.2", + "version": "1.75.3", "description": "A web-based weekly task management application that organizes to-dos and calendar events in a single, intuitive weekly view", "main": "index.js", "scripts": { diff --git a/src/components/WeeklyView.tsx b/src/components/WeeklyView.tsx index 591ab13..d44067c 100644 --- a/src/components/WeeklyView.tsx +++ b/src/components/WeeklyView.tsx @@ -7681,6 +7681,10 @@ export default function WeeklyView() { ); })} + {/* End-of-day 24:00 label */} +
+ {timeFormat === '24h' ? '24' : '12 AM'} +
)} @@ -8269,6 +8273,8 @@ export default function WeeklyView() { ); })} + {/* End-of-day 24:00 line */} +
{/* All Day Events Section */} diff --git a/src/lib/calendar-events.ts b/src/lib/calendar-events.ts index e494441..5e2fee1 100644 --- a/src/lib/calendar-events.ts +++ b/src/lib/calendar-events.ts @@ -396,21 +396,19 @@ export const getCalendarEvents = async ( continue; } - // Get user calendars to identify which ones to fetch events from - const freshCalendars = await getAppleCalendars(email, appPassword); + // Use stored calendars from DB for filtering (avoids extra iCloud login) + const storedCalendars = (connection.calendars && Array.isArray(connection.calendars) && connection.calendars.length > 0) + ? (connection.calendars as any[]).filter((c: any) => c.selected !== false) + : []; - // Use stored selection state if available, otherwise use all fresh calendars - let calendars = freshCalendars; - if (connection.calendars && Array.isArray(connection.calendars) && connection.calendars.length > 0) { - const storedCalendars = connection.calendars as any[]; - calendars = freshCalendars.filter(fc => { - const stored = storedCalendars.find((sc: any) => sc.id === fc.id); - return stored ? stored.selected !== false : true; - }); + if (storedCalendars.length === 0) { + console.log('[CALENDAR] Apple: no stored calendars, skipping (connect/refresh calendars in settings)'); + continue; } - const calendarIds = calendars.map(c => c.id); - // Batch fetch: single login, single calendar list, then fetch all calendars + const calendarIds = storedCalendars.map((c: any) => c.id); + + // Single login: batch fetch events for all selected calendars console.log(`[CALENDAR] Apple: batch fetching ${calendarIds.length} calendars with single connection`); const batchResults = await getAppleEventsBatch( email, @@ -422,6 +420,7 @@ export const getCalendarEvents = async ( for (const [calendarId, calendarEvents] of batchResults) { console.log(`[CALENDAR] Fetched ${calendarEvents.length} events from Apple calendar ${calendarId}`); + const calMeta = storedCalendars.find((c: any) => c.id === calendarId); events = events.concat(calendarEvents.map((event: any) => { const isDateOnly = (s: string) => s && !s.includes('T'); @@ -444,8 +443,8 @@ export const getCalendarEvents = async ( isRecurring: event.isRecurring, source: 'apple' as const, calendarId, - calendarTitle: calendars.find(c => c.id === calendarId)?.title || 'Apple Calendar', - backgroundColor: calendars.find(c => c.id === calendarId)?.color || '#FF3B30', + calendarTitle: calMeta?.title || 'Apple Calendar', + backgroundColor: calMeta?.color || '#FF3B30', reminders: event.reminders as EventReminder[] || undefined, busyStatus: event.busyStatus as BusyStatus || undefined, visibility: event.visibility as EventVisibility || undefined, @@ -463,55 +462,19 @@ export const getCalendarEvents = async ( continue; } - // Fetch live calendar list from Synology to detect deleted calendars - let calendarIds: string[] = []; - let calendars: any[] = []; - let freshCalendars: any[] = []; + // Use stored calendars from DB (avoids extra Synology login) + const storedCalendars = (connection.calendars && Array.isArray(connection.calendars) && connection.calendars.length > 0) + ? (connection.calendars as any[]).filter((c: any) => c.selected !== false) + : []; - try { - freshCalendars = await getSynologyCalendars(serverUrl, username, password); - } catch (err) { - console.error('[CALENDAR] Synology: failed to fetch calendar list:', err); - } - - const freshIds = new Set(freshCalendars.map(c => c.id)); - - if (connection.calendars && Array.isArray(connection.calendars) && connection.calendars.length > 0) { - const storedCalendars = connection.calendars as any[]; - // Remove calendars that no longer exist on the server - calendars = storedCalendars.filter((c: any) => freshIds.has(c.id)); - - if (calendars.length < storedCalendars.length) { - const removed = storedCalendars.length - calendars.length; - console.log(`[CALENDAR] Synology: pruned ${removed} deleted calendar(s) from stored list`); - // Update stored calendars in DB to remove stale entries - try { - await prisma.calendarConnection.update({ - where: { id: connection.id }, - data: { calendars: calendars }, - }); - } catch (dbErr) { - console.error('[CALENDAR] Synology: failed to update stored calendars:', dbErr); - } - } - - calendarIds = calendars - .filter((c: any) => c.selected !== false) - .map((c: any) => c.id); - console.log('[CALENDAR] Synology: using stored calendars, selected:', calendarIds.length, 'of', calendars.length); - } else { - // No stored calendars: use fresh list - console.log('[CALENDAR] Synology: no stored calendars, using fresh list'); - calendars = freshCalendars; - calendarIds = freshCalendars.map(c => c.id); - } - - if (calendarIds.length === 0) { - console.log('[CALENDAR] Synology: no calendars selected, skipping'); + if (storedCalendars.length === 0) { + console.log('[CALENDAR] Synology: no stored calendars, skipping'); continue; } - // Batch fetch: single login, single calendar list, then fetch all calendars + const calendarIds = storedCalendars.map((c: any) => c.id); + + // Single login: batch fetch events for all selected calendars console.log(`[CALENDAR] Synology: batch fetching ${calendarIds.length} calendars with single connection`); const batchResults = await getSynologyEventsBatch( serverUrl, @@ -524,8 +487,7 @@ export const getCalendarEvents = async ( for (const [calendarId, calendarEvents] of batchResults) { console.log(`[CALENDAR] Synology: fetched ${calendarEvents.length} events from calendar ${calendarId}`); - const calendarData = calendars.find(c => c.id === calendarId); - const freshCal = freshCalendars.find(c => c.id === calendarId); + const calMeta = storedCalendars.find((c: any) => c.id === calendarId); events = events.concat(calendarEvents.map((event: any) => { const isDateOnly = (s: string) => s && !s.includes('T'); @@ -548,8 +510,8 @@ export const getCalendarEvents = async ( isRecurring: event.isRecurring, source: 'synology' as const, calendarId, - calendarTitle: calendarData?.title || 'Synology Calendar', - backgroundColor: calendarData?.backgroundColor || calendarData?.color || freshCal?.color || '#1b85ff', + calendarTitle: calMeta?.title || 'Synology Calendar', + backgroundColor: calMeta?.backgroundColor || calMeta?.color || '#1b85ff', reminders: event.reminders as EventReminder[] || undefined, busyStatus: event.busyStatus as BusyStatus || undefined, visibility: event.visibility as EventVisibility || undefined,