@tanstack/offline-transactions
Version:
Offline-first transaction capabilities for TanStack DB
99 lines (80 loc) • 2.15 kB
text/typescript
import type { OnlineDetector } from '../types'
/**
* Web-based online detector that uses browser APIs.
* Listens for:
* - `window.online` event for network connectivity changes
* - `document.visibilitychange` event for tab/window focus changes
*/
export class WebOnlineDetector implements OnlineDetector {
private listeners: Set<() => void> = new Set()
private isListening = false
constructor() {
this.startListening()
}
private startListening(): void {
if (this.isListening) {
return
}
this.isListening = true
if (typeof window !== `undefined`) {
window.addEventListener(`online`, this.handleOnline)
document.addEventListener(`visibilitychange`, this.handleVisibilityChange)
}
}
private stopListening(): void {
if (!this.isListening) {
return
}
this.isListening = false
if (typeof window !== `undefined`) {
window.removeEventListener(`online`, this.handleOnline)
document.removeEventListener(
`visibilitychange`,
this.handleVisibilityChange,
)
}
}
private handleOnline = (): void => {
this.notifyListeners()
}
private handleVisibilityChange = (): void => {
if (document.visibilityState === `visible`) {
this.notifyListeners()
}
}
private notifyListeners(): void {
for (const listener of this.listeners) {
try {
listener()
} catch (error) {
console.warn(`OnlineDetector 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 {
if (typeof navigator !== `undefined`) {
return navigator.onLine
}
return true
}
dispose(): void {
this.stopListening()
this.listeners.clear()
}
}
/**
* @deprecated Use `WebOnlineDetector` instead. This alias is kept for backwards compatibility.
*/
export const DefaultOnlineDetector = WebOnlineDetector