import { Disclosure, DisclosureContent, DisclosureProvider, } from "@ariakit/react"; import { useAppConfig } from "../AppConfig/AppConfig.tsx"; import { useLastSuccessfulSyncTs, useSyncLog, useSyncState, type SyncState, } from "../store/index.tsx"; import type { SyncAttempt } from "../store/types.ts"; import type { FailurePayload } from "../types.ts"; import { log } from "./style.css.ts"; import { SyncIcon } from "./SyncIcon.tsx"; function SyncActionSuccess(props: { heading: string; items: { id: string; name: string; deleted: boolean }[]; }) { const { heading, items } = props; return (
{heading}
{items.length > 0 ? :
Everything up to date.
}
); } const failureToLabel: Record = { NETWORK_ERROR: "A network error occurred.", API_ERROR: "Server responded with error ", UNKNOWN_ERROR: "An unexpected error ocurred. Try restarting the app.", VALIDATION_ERROR: "Data validation error occurred. Try restarting the app.", }; function SyncActionFailure(props: { heading: string; failure: FailurePayload; }) { const { heading, failure } = props; const label = failureToLabel[failure.type]; return (
{heading} {": "} {failure.type === "API_ERROR" ? ` ${label} ${failure.code}.` : ` ${label}`}
); } const syncStateToLabel: Record = { WAITING: "Waiting for additional changes...", IDLE: "Sync enabled. Waiting for changes.", AUTHENTICATING: "Verifying identity...", ERROR: "Last sync unsuccessful. Waiting for changes.", INACTIVE: "Sync not enabled. Log in or join to enable.", SYNCING: "Syncing...", }; export function SyncLogList(props: { syncState: SyncState; syncLog: SyncAttempt[]; lastSuccessfulSyncTs: number | null; }) { const { syncLog, syncState, lastSuccessfulSyncTs } = props; const { fmt } = useAppConfig(); return (
{syncStateToLabel[syncState]}
{lastSuccessfulSyncTs ? `Last successful sync at: ${fmt.dateTime(lastSuccessfulSyncTs)}` : "Not synced yet."}
{syncLog.map((logItem) => { const isFailure = logItem.pull?.type === "FAILURE" || logItem.push?.type == "FAILURE"; const itemsSynced = (logItem.pull?.type === "SUCCESS" ? logItem.pull.value.pulled.length : 0) + (logItem.push?.type === "SUCCESS" ? logItem.push.value.pushed.length + logItem.push.value.pulled.length : 0); return ( {isFailure ? <>
Sync attempt failed
{fmt.dateTime(logItem.startedTs)}
: <>
{"Sync successful. "} {itemsSynced === 0 ? "Everything up to date." : fmt.plural(itemsSynced, { one: "1 item synced.", other: "# items synced.", }) }
{fmt.dateTime(logItem.startedTs)}
}
{logItem.pull && ( <> {logItem.pull.type === "SUCCESS" ? : } )} {logItem.push && ( <> {logItem.push.type === "SUCCESS" ? <> : } )}
); })}
); } export function SyncLog() { const syncState = useSyncState(); const syncLog = useSyncLog(); const lastSuccessfulSyncTs = useLastSuccessfulSyncTs(); return ( ); }