53 lines
1.4 KiB
TypeScript
53 lines
1.4 KiB
TypeScript
|
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>
|
||
|
}
|
||
|
}
|