UNPKG

@tanstack/offline-transactions

Version:

Offline-first transaction capabilities for TanStack DB

126 lines (103 loc) 3.12 kB
import NetInfo from '@react-native-community/netinfo' import { AppState } from 'react-native' import type { AppStateStatus, NativeEventSubscription } from 'react-native' import type { OnlineDetector } from '../types' /** * React Native online detector that uses RN APIs. * Listens for: * - Network connectivity changes via `@react-native-community/netinfo` * - App state changes (foreground/background) via `AppState` */ export class ReactNativeOnlineDetector implements OnlineDetector { private listeners: Set<() => void> = new Set() private netInfoUnsubscribe: (() => void) | null = null private appStateSubscription: NativeEventSubscription | null = null private isListening = false private wasConnected = true constructor() { this.startListening() } private startListening(): void { if (this.isListening) { return } this.isListening = true if (typeof NetInfo.fetch === `function`) { void NetInfo.fetch() .then((state) => { this.wasConnected = this.toConnectivityState(state) }) .catch(() => { // Ignore initial fetch failures and rely on subscription updates. }) } // Subscribe to network state changes this.netInfoUnsubscribe = NetInfo.addEventListener((state) => { const isConnected = this.toConnectivityState(state) // Only notify when transitioning to online if (isConnected && !this.wasConnected) { this.notifyListeners() } this.wasConnected = isConnected }) // Subscribe to app state changes (foreground/background) this.appStateSubscription = AppState.addEventListener( `change`, this.handleAppStateChange, ) } private handleAppStateChange = (nextState: AppStateStatus): void => { // Notify when app becomes active (foreground) if (nextState === `active`) { this.notifyListeners() } } private stopListening(): void { if (!this.isListening) { return } this.isListening = false if (this.netInfoUnsubscribe) { this.netInfoUnsubscribe() this.netInfoUnsubscribe = null } if (this.appStateSubscription) { this.appStateSubscription.remove() this.appStateSubscription = null } } private notifyListeners(): void { for (const listener of this.listeners) { try { listener() } catch (error) { console.warn(`ReactNativeOnlineDetector listener error:`, error) } } } subscribe(callback: () => void): () => void { this.listeners.add(callback) return () => { this.listeners.delete(callback) if (this.listeners.size === 0) { this.stopListening() } } } notifyOnline(): void { this.notifyListeners() } isOnline(): boolean { return this.wasConnected } dispose(): void { this.stopListening() this.listeners.clear() } private toConnectivityState(state: { isConnected: boolean | null isInternetReachable: boolean | null }): boolean { return !!state.isConnected && state.isInternetReachable !== false } }