Menu
Public repository / 0216cf0f6008aae88a648a82e9b3a462a6688302
AkurAI-Mail / src/lib/webmail/sync.svelte.ts
Latest change 22202d1bde69be4ace8a299dffd91f8ff24378df - Recover deployed webmail frontend (frontend parity with EC2 a6afffc) by Ólafur Búi Ólafsson
import { retryDelay, type SyncErrorKind } from "./sync";
/** Reactive sync state: status, last success, current error and an auto-retry timer. */
export function createSyncState() {
let status = $state<"idle" | "syncing">("idle");
let lastSyncAt = $state<number | null>(null);
let errorKind = $state<SyncErrorKind | null>(null);
let dismissed = $state(false);
let retryCount = $state(0);
let timer: ReturnType<typeof setTimeout> | null = null;
function clearTimer() {
if (timer) clearTimeout(timer);
timer = null;
}
/** Records a failure; schedules `retry` with backoff unless the session expired. */
function reportError(kind: SyncErrorKind, retry?: () => void) {
status = "idle";
errorKind = kind;
dismissed = false;
clearTimer();
if (retry && kind !== "auth-expired") {
const delay = retryDelay(retryCount);
retryCount += 1;
timer = setTimeout(retry, delay);
}
}
function reportSuccess() {
status = "idle";
errorKind = null;
retryCount = 0;
lastSyncAt = Date.now();
clearTimer();
}
function retryNow(run: () => void) {
clearTimer();
run();
}
return {
get status() { return status; },
set status(value) { status = value; },
get lastSyncAt() { return lastSyncAt; },
get errorKind() { return errorKind; },
get dismissed() { return dismissed; },
get retryCount() { return retryCount; },
reportError,
reportSuccess,
retryNow,
dismiss: () => { dismissed = true; },
};
}
export type SyncState = ReturnType<typeof createSyncState>;