perf: load calendar events instantly, sync CalDAV in background
Split loadEvents into two functions: loadEvents (instant DB read) and syncAndReload (background CalDAV sync + reload). Events now appear immediately when switching to the Calendar tab instead of waiting for the CalDAV sync to complete.
This commit is contained in:
@@ -405,7 +405,7 @@ CalDAV sync with external calendar servers (e.g., Radicale) using `tsdav` and `i
|
|||||||
**Sync Triggers (client-side via `CaldavConfigService.sync()`):**
|
**Sync Triggers (client-side via `CaldavConfigService.sync()`):**
|
||||||
- **Login** (`login.tsx`): After successful authentication
|
- **Login** (`login.tsx`): After successful authentication
|
||||||
- **Auto-login** (`AuthGuard.tsx`): After `loadStoredUser()` if authenticated
|
- **Auto-login** (`AuthGuard.tsx`): After `loadStoredUser()` if authenticated
|
||||||
- **Calendar timer** (`calendar.tsx`): Every 10s while Calendar tab is focused, via `setInterval` in `useFocusEffect`
|
- **Calendar timer** (`calendar.tsx`): Events load instantly from DB on focus (`loadEvents`), CalDAV sync runs in background (`syncAndReload`) and reloads events after. Repeats every 10s via `setInterval`
|
||||||
- **Sync button** (`settings.tsx`): Manual trigger in CaldavSettings
|
- **Sync button** (`settings.tsx`): Manual trigger in CaldavSettings
|
||||||
|
|
||||||
**Lazy sync (server-side in ChatService):**
|
**Lazy sync (server-side in ChatService):**
|
||||||
@@ -618,7 +618,7 @@ NODE_ENV=development # development = pretty logs, production = JSON
|
|||||||
- Orange dot indicator for days with events
|
- Orange dot indicator for days with events
|
||||||
- Tap-to-open modal overlay showing EventCards for selected day
|
- Tap-to-open modal overlay showing EventCards for selected day
|
||||||
- Supports events from adjacent months visible in grid
|
- Supports events from adjacent months visible in grid
|
||||||
- Uses `useFocusEffect` for automatic reload on tab focus with periodic CalDAV sync (10s interval while focused)
|
- Events load instantly from local DB on tab focus, CalDAV sync runs non-blocking in background (`syncAndReload`) with 10s interval
|
||||||
- DeleteEventModal integration for recurring event deletion with three modes
|
- DeleteEventModal integration for recurring event deletion with three modes
|
||||||
- EventOverlay hides when DeleteEventModal is open (fixes modal stacking on web)
|
- EventOverlay hides when DeleteEventModal is open (fixes modal stacking on web)
|
||||||
- Chat screen fully functional with FlashList, message sending, and event confirm/reject
|
- Chat screen fully functional with FlashList, message sending, and event confirm/reject
|
||||||
|
|||||||
@@ -85,15 +85,9 @@ const Calendar = () => {
|
|||||||
|
|
||||||
const { events, setEvents, deleteEvent } = useEventsStore();
|
const { events, setEvents, deleteEvent } = useEventsStore();
|
||||||
|
|
||||||
// Sync CalDAV then load events for current view
|
// Load events from local DB (fast, no network sync)
|
||||||
const loadEvents = useCallback(async () => {
|
const loadEvents = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
try {
|
|
||||||
await CaldavConfigService.sync();
|
|
||||||
} catch {
|
|
||||||
// No CalDAV config or sync failed — not critical
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate first visible day (up to 6 days before month start)
|
// Calculate first visible day (up to 6 days before month start)
|
||||||
const firstOfMonth = new Date(currentYear, monthIndex, 1);
|
const firstOfMonth = new Date(currentYear, monthIndex, 1);
|
||||||
const dayOfWeek = firstOfMonth.getDay();
|
const dayOfWeek = firstOfMonth.getDay();
|
||||||
@@ -119,16 +113,25 @@ const Calendar = () => {
|
|||||||
}
|
}
|
||||||
}, [monthIndex, currentYear, setEvents]);
|
}, [monthIndex, currentYear, setEvents]);
|
||||||
|
|
||||||
// Load events when tab gains focus or month/year changes
|
// Sync CalDAV in background, then reload events
|
||||||
// NOTE: Wrapper needed because loadEvents is async (returns Promise)
|
const syncAndReload = useCallback(async () => {
|
||||||
// and useFocusEffect expects a sync function (optionally returning cleanup)
|
try {
|
||||||
|
await CaldavConfigService.sync();
|
||||||
|
await loadEvents();
|
||||||
|
} catch {
|
||||||
|
// Sync failed — not critical
|
||||||
|
}
|
||||||
|
}, [loadEvents]);
|
||||||
|
|
||||||
|
// Load events instantly on focus, then sync in background periodically
|
||||||
useFocusEffect(
|
useFocusEffect(
|
||||||
useCallback(() => {
|
useCallback(() => {
|
||||||
loadEvents();
|
loadEvents();
|
||||||
|
syncAndReload();
|
||||||
|
|
||||||
const interval = setInterval(loadEvents, 10_000);
|
const interval = setInterval(syncAndReload, 10_000);
|
||||||
return () => clearInterval(interval);
|
return () => clearInterval(interval);
|
||||||
}, [loadEvents]),
|
}, [loadEvents, syncAndReload]),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Re-open overlay after back navigation from editEvent
|
// Re-open overlay after back navigation from editEvent
|
||||||
|
|||||||
Reference in New Issue
Block a user