Files
webmail/lib/clear-cached-data.ts
Linus Rath 9041cbcd08 fix: keep iCal subscriptions on refresh, rename calendars of any colour
- send a calendar's colour only when the user changed it: Stalwart 1.0
  accepts only #rgb, #rrggbb or a CSS name, so renaming a calendar that
  another client coloured with an 8-digit hex (Apple Calendar) failed
- "Refresh cached data" kept nothing of the calendar store's persisted
  state, so it deleted the user's iCal subscriptions, which exist only
  there; keep them and drop the rest
- show a notice with a retry when the task list fails to load; it keeps
  the tasks it had
- treat a method-level error on creating a task as a failure with its
  JMAP type instead of "no id returned"
2026-09-25 19:41:00 +02:00

70 lines
2.3 KiB
TypeScript

import { evictAll } from '@/lib/account-state-manager';
// localStorage keys holding server-derived, re-fetchable caches. The "Refresh
// cached data" action clears these so a stale or wrong-account view can be
// fixed WITHOUT signing out (which would drop the whole account list).
//
// Deliberately excluded:
// - 'account-registry' / 'auth-storage' → keep accounts + sessions
// - 'settings-storage' / 'theme-storage' / 'locale-storage' → user prefs
// - 'template-storage' / 'smime-preferences' → user-created content
const CACHE_STORAGE_KEYS = [
'email-snapshot',
'identity-storage',
'contact-storage',
'calendar-storage',
'calendar-notification-storage',
];
/**
* The user's iCal subscriptions exist only in the calendar store's persisted
* state, next to its caches: keep them and drop the rest.
*/
function clearCalendarStorage(storage: Storage): void {
let persisted: { state?: { icalSubscriptions?: unknown }; version?: unknown } | null = null;
try {
persisted = JSON.parse(storage.getItem('calendar-storage') ?? 'null');
} catch {
/* not ours to read: drop it */
}
const subscriptions = persisted?.state?.icalSubscriptions;
if (!Array.isArray(subscriptions) || subscriptions.length === 0) {
storage.removeItem('calendar-storage');
return;
}
storage.setItem('calendar-storage', JSON.stringify({
state: { icalSubscriptions: subscriptions },
version: persisted?.version ?? 0,
}));
}
/**
* Clear cached, server-derived data (contacts, calendars, identities, and the
* in-memory per-account snapshots), then reload so everything is re-fetched
* fresh for the active account. Accounts, sessions and iCal subscriptions are
* preserved — this is the non-destructive alternative to the browser's
* "clear site data", which also wipes the account list.
*/
export function clearCachedData(): void {
// Drop the in-memory per-account store snapshots so a reload can't restore
// stale cached state for any account.
try {
evictAll();
} catch {
/* snapshots are best-effort */
}
if (typeof window === 'undefined') return;
for (const key of CACHE_STORAGE_KEYS) {
try {
if (key === 'calendar-storage') clearCalendarStorage(window.localStorage);
else window.localStorage.removeItem(key);
} catch {
/* ignore storage access errors */
}
}
window.location.reload();
}