Menu
Public repository / 7a6a24a4e46f9f1d964c5593c076f9bdf638fea0
AkurAI-Mail / src/lib/webmail/sync.ts
Latest change 22202d1bde69be4ace8a299dffd91f8ff24378df - Recover deployed webmail frontend (frontend parity with EC2 a6afffc) by Ólafur Búi Ólafsson
/** Pure helpers behind the webmail sync status and error banner. */
export type SyncErrorKind = "offline" | "auth-expired" | "server-error";
export const SYNC_ERROR_MESSAGES: Record<SyncErrorKind, string> = {
offline: "You're offline. Showing the last synced messages.",
"auth-expired": "Your session expired. Sign in again to resume syncing.",
"server-error": "The mail server had a problem. Showing the last synced messages.",
};
export const RETRY_BASE_MS = 2000;
export const RETRY_MAX_MS = 60000;
/** Exponential backoff: 2s, 4s, 8s ... capped at one minute. */
export function retryDelay(attempt: number) {
return Math.min(RETRY_BASE_MS * 2 ** attempt, RETRY_MAX_MS);
}
export function classifySyncError(error: unknown, response?: { status: number }, online = typeof navigator === "undefined" ? true : navigator.onLine): SyncErrorKind {
if (response?.status === 401) return "auth-expired";
if (online === false || error instanceof TypeError) return "offline";
return "server-error";
}
/** "Synced just now", "Synced 12s ago", "Synced 3m ago", "Synced 2h ago". */
export function syncedLabel(lastSyncAt: number | null, now = Date.now()) {
if (!lastSyncAt) return "Never synced";
const seconds = Math.max(0, Math.round((now - lastSyncAt) / 1000));
if (seconds < 5) return "Synced just now";
if (seconds < 60) return `Synced ${seconds}s ago`;
const minutes = Math.round(seconds / 60);
if (minutes < 60) return `Synced ${minutes}m ago`;
return `Synced ${Math.round(minutes / 60)}h ago`;
}