Changed network detection to only mark as offline on actual network errors, not on HTTP errors like 404. This fixes the issue where the app shows 'You are offline' even when connected, which happens when accessing through a reverse proxy where the /api/health endpoint might not be properly routed. Now the app will show as online as long as it can reach the server (any HTTP response), and only show offline on true connection failures. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
91 lines
2.6 KiB
TypeScript
91 lines
2.6 KiB
TypeScript
import { Middleware } from '@reduxjs/toolkit';
|
|
import { RootState } from '../store';
|
|
import { setOnlineStatus } from '../slices/networkSlice';
|
|
import { addPendingAction, removePendingAction, incrementRetryCount } from '../slices/offlineSlice';
|
|
|
|
/**
|
|
* Offline middleware - intercepts actions and queues them when offline
|
|
*/
|
|
export const offlineMiddleware: Middleware<{}, RootState> = (store) => (next) => (action: any) => {
|
|
const state = store.getState();
|
|
const isOnline = state.network?.isOnline ?? true;
|
|
|
|
// Check if this is an async action that should be queued
|
|
const isOfflineableAction =
|
|
action.type?.includes('/create') ||
|
|
action.type?.includes('/update') ||
|
|
action.type?.includes('/delete');
|
|
|
|
// If offline and action should be queued
|
|
if (!isOnline && isOfflineableAction && action.meta?.requestId) {
|
|
console.log('[Offline Middleware] Queuing action:', action.type);
|
|
|
|
// Queue the action
|
|
store.dispatch(
|
|
addPendingAction({
|
|
type: action.type,
|
|
payload: action.payload,
|
|
})
|
|
);
|
|
|
|
// Still process the optimistic update
|
|
return next(action);
|
|
}
|
|
|
|
// If online, process normally
|
|
return next(action);
|
|
};
|
|
|
|
/**
|
|
* Network status detector - listens for online/offline events
|
|
*/
|
|
export const setupNetworkDetection = (dispatch: any) => {
|
|
if (typeof window === 'undefined') return;
|
|
|
|
const handleOnline = () => {
|
|
console.log('[Network] Connection restored');
|
|
dispatch(setOnlineStatus(true));
|
|
};
|
|
|
|
const handleOffline = () => {
|
|
console.log('[Network] Connection lost');
|
|
dispatch(setOnlineStatus(false));
|
|
};
|
|
|
|
// Listen to browser online/offline events
|
|
window.addEventListener('online', handleOnline);
|
|
window.addEventListener('offline', handleOffline);
|
|
|
|
// Periodic connectivity check
|
|
const checkConnectivity = async () => {
|
|
try {
|
|
const startTime = Date.now();
|
|
const response = await fetch('/api/health', {
|
|
method: 'HEAD',
|
|
cache: 'no-cache',
|
|
});
|
|
const latency = Date.now() - startTime;
|
|
|
|
// Consider online if we got ANY response (even 404)
|
|
// Only mark offline on actual network errors
|
|
dispatch(setOnlineStatus(true));
|
|
} catch (error) {
|
|
// Only network errors (no connection) should mark as offline
|
|
dispatch(setOnlineStatus(false));
|
|
}
|
|
};
|
|
|
|
// Check connectivity every 30 seconds
|
|
const intervalId = setInterval(checkConnectivity, 30000);
|
|
|
|
// Initial check
|
|
checkConnectivity();
|
|
|
|
// Cleanup function
|
|
return () => {
|
|
window.removeEventListener('online', handleOnline);
|
|
window.removeEventListener('offline', handleOffline);
|
|
clearInterval(intervalId);
|
|
};
|
|
};
|