import { type Signal, useComputed, useSignal } from '@preact/signals' import { useEffect } from 'preact/hooks' import { IS_BROWSER } from '$fresh/runtime.ts' type NetworkConnection = { addEventListener: ( type: 'change', listener: (event: Event) => void | Promise, ) => void } export default function IsOnline( { online, offline }: { online?: string; offline: string }, ) { if (!IS_BROWSER) { return online ? : {online} } const status = useSignal(true) const displayed = useComputed(() => { if (status.value && online) { return {online} } if (status.value) { return } return {offline} }) const connection = 'connection' in navigator ? navigator.connection as NetworkConnection : null useEffect(() => { openSocket(status) 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()) }) }