2026-01-11 16:16:49 +00:00
|
|
|
/**
|
|
|
|
|
* Network Error Tracker
|
|
|
|
|
* Tracks recent network errors to show offline indicator even when browser reports online
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
import { getErrorCategory } from './apiErrorHandler';
|
2026-01-15 16:03:35 +00:00
|
|
|
import type { ApiError } from '@/schemas/apiSchemas';
|
2026-01-11 16:16:49 +00:00
|
|
|
|
|
|
|
|
let recentNetworkError: Error | ApiError | null = null;
|
|
|
|
|
let networkErrorTimestamp: number | null = null;
|
|
|
|
|
const NETWORK_ERROR_TIMEOUT = 30000; // Show indicator for 30 seconds after network error
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Records a network error for tracking
|
|
|
|
|
* @param error - The error that occurred
|
|
|
|
|
*/
|
|
|
|
|
export function recordNetworkError(error: Error | ApiError | unknown): void {
|
|
|
|
|
const category = getErrorCategory(error);
|
|
|
|
|
if (category === 'network' || category === 'timeout') {
|
2026-01-13 18:47:57 +00:00
|
|
|
recentNetworkError =
|
|
|
|
|
error instanceof Error ||
|
|
|
|
|
(error && typeof error === 'object' && 'message' in error)
|
|
|
|
|
? (error as Error | ApiError)
|
|
|
|
|
: new Error(String(error));
|
2026-01-11 16:16:49 +00:00
|
|
|
networkErrorTimestamp = Date.now();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Clears the recorded network error
|
|
|
|
|
*/
|
|
|
|
|
export function clearNetworkError(): void {
|
|
|
|
|
recentNetworkError = null;
|
|
|
|
|
networkErrorTimestamp = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Checks if there's a recent network error
|
|
|
|
|
* @returns true if there's a network error within the timeout window
|
|
|
|
|
*/
|
|
|
|
|
export function hasRecentNetworkError(): boolean {
|
|
|
|
|
if (!recentNetworkError || !networkErrorTimestamp) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check if error is still within timeout window
|
|
|
|
|
const timeSinceError = Date.now() - networkErrorTimestamp;
|
|
|
|
|
if (timeSinceError > NETWORK_ERROR_TIMEOUT) {
|
|
|
|
|
// Clear expired error
|
|
|
|
|
clearNetworkError();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Gets the recent network error if any
|
|
|
|
|
* @returns The recent network error or null
|
|
|
|
|
*/
|
|
|
|
|
export function getRecentNetworkError(): Error | ApiError | null {
|
|
|
|
|
if (hasRecentNetworkError()) {
|
|
|
|
|
return recentNetworkError;
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|