website/islands/IsOnline.tsx

53 lines
1.4 KiB
TypeScript
Raw Normal View History

import { type Signal, useSignal } from '@preact/signals'
import { useEffect } from 'preact/hooks'
import { JSX } from 'preact'
import { requestApi } from ':src/utils.ts'
type NetworkConnection = {
addEventListener: (
type: 'change',
listener: (event: Event) => void | Promise<void>,
) => void
}
export default function IsOnline(
{ online, offline }: { online?: string; offline: string },
) {
const status = useSignal(offline)
const connection = 'connection' in navigator
? navigator.connection as NetworkConnection
: null
useEffect(() => {
// Update connection status on network changes
connection?.addEventListener('change', () => {
updateNetworkStatus(status, online, offline)
})
// Update connection status on 1st load
updateNetworkStatus(status, online, offline)
// Update connection status on interval (10s)
setInterval(() => updateNetworkStatus(status, online, offline), 10_000)
})
return <>{status}</>
}
async function updateNetworkStatus(
status: Signal<JSX.Element>,
online: string | undefined,
offline: string,
) {
const isOnline = await requestApi<void, boolean>(
'/serviceworker/is-online',
'POST',
).catch(() => false)
if (isOnline) {
status.value = online === undefined
? <span style={{ display: 'none' }}></span>
: <span>{online}</span>
} else {
status.value = <span class={'island__is_online'}>{offline}</span>
}
}