mirror of
https://github.com/bulwarkmail/native.git
synced 2026-11-01 08:06:13 +00:00
zustand's JSON storage serialises the whole partialized slice and writes it to AsyncStorage on every set(), including ones that only flip `loading`. Opening one unread message rewrote the mail cache about five times. `createPersistStorage` now coalesces writes per store: - a slice whose fields are the same references as the last one is dropped without serialising; the email and contacts slices are built through `memoizeSlice`, so a set() that only touches UI flags hands over the same slice - other changes wait up to 1 s and only the newest is serialised, and JSON identical to the stored row, or to the row just hydrated from, isn't written again - pending writes are flushed when the app leaves the foreground and when an account is signed out - the account registry is still written straight away, since the headless push task reads it from AsyncStorage - "Refresh cached data" removes the rows through the stores, so their storage forgets the old JSON and writes the re-fetched data back
50 lines
2.1 KiB
TypeScript
50 lines
2.1 KiB
TypeScript
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
import { useEmailStore } from '../stores/email-store';
|
|
import { useContactsStore } from '../stores/contacts-store';
|
|
import { useCalendarStore } from '../stores/calendar-store';
|
|
|
|
// Persisted, server-derived caches (Zustand persist names). The "Refresh
|
|
// cached data" action drops these so a stale or wrong-account view can be
|
|
// fixed WITHOUT signing out (which would drop the whole account list).
|
|
// Mirrors the webmail's lib/clear-cached-data.ts.
|
|
//
|
|
// Deliberately excluded: 'account-registry' (accounts), 'webmail:settings:v1'
|
|
// / 'webmail:locale:v1' (preferences), 'webmail:templates:v1' /
|
|
// 'webmail:keywords:v1' / 'calendar-subscriptions' (user-created content),
|
|
// the offline body cache (managed on its own pane) and push registrations.
|
|
export const CACHE_STORAGE_KEYS = [
|
|
'email-cache',
|
|
'contacts-cache',
|
|
'calendar-cache',
|
|
'webmail:calendar:hidden:v1',
|
|
'webmail:contacts:category:v1',
|
|
];
|
|
|
|
/**
|
|
* Clear cached, server-derived data (mail list snapshots, contacts,
|
|
* calendars) and re-fetch everything for the active account. Accounts and
|
|
* sessions are preserved.
|
|
*/
|
|
export async function clearCachedData(): Promise<void> {
|
|
// Through the stores first: their storage drops any pending write and
|
|
// forgets what it last wrote, so the re-fetched data is written back even
|
|
// where it matches the old cache.
|
|
for (const store of [useEmailStore, useContactsStore, useCalendarStore]) {
|
|
store.persist.clearStorage();
|
|
}
|
|
try {
|
|
await AsyncStorage.multiRemove(CACHE_STORAGE_KEYS);
|
|
} catch {
|
|
// storage errors are non-fatal - the re-fetch below still refreshes state
|
|
}
|
|
const results = await Promise.allSettled([
|
|
useEmailStore.getState().fetchMailboxes().then(() => useEmailStore.getState().refreshEmails()),
|
|
useContactsStore.getState().refresh(),
|
|
useCalendarStore.getState().refresh(),
|
|
]);
|
|
const failure = results.find((r): r is PromiseRejectedResult => r.status === 'rejected');
|
|
if (failure) {
|
|
throw failure.reason instanceof Error ? failure.reason : new Error(String(failure.reason));
|
|
}
|
|
}
|