import { type Signal, useComputed, useSignal } from '@preact/signals' import { useEffect } from 'preact/hooks' type NetworkConnection = { addEventListener: ( type: 'change', listener: (event: Event) => void | Promise, ) => void } declare global { interface Navigator { connection?: NetworkConnection } } export default function IsOnline( { online, offline }: { online?: string; offline: string }, ) { const status = useSignal(true) const displayed = useComputed(() => { if (status.value && online) { return {online} } if (status.value) { return } return {offline} }) useEffect(() => { openSocket(status) navigator.connection?.addEventListener('change', () => { fetch('/api/serviceworker/is-online') .then(() => status.value = true) .catch(() => status.value = false) }) }, []) return <>{displayed} } function openSocket(status: Signal) { const socket = new WebSocket( `wss://${location.host}/api/serviceworker/is-online`, ) socket.addEventListener('open', () => { status.value = true const id = Number(sessionStorage.getItem('$cohabit.is-online.id') ?? -1) clearInterval(id) }) socket.addEventListener('close', () => { status.value = false // Try reconnect every 5s const id = setInterval(() => openSocket(status), 5_000) sessionStorage.setItem('$cohabit.is-online.id', id.toString()) }) }