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,