// The live feed of `GET /api/messages/stream`, one `SwarmMessage` per event. // The stream has no event id, so a reconnect sends the history again from the // start; the list therefore empties each time the connection opens, and the // replay refills it. Not `useSwarmTermStream`: that one keeps its rows across // a reconnect, which here would list every message twice. import { useEffect, useState } from "preact/hooks"; import type { SwarmMessage } from "./messages.js"; import { messagesUrl, newest } from "./messages.js"; export type ConnectionState = "connecting" | "open" | "reconnecting" | "closed"; /** The most messages the page holds; older ones drop off. */ export const MAX_MESSAGES = 2000; export function useMessageStream(sinceMinutes: number): { messages: SwarmMessage[]; connection: ConnectionState; } { const [messages, setMessages] = useState([]); const [connection, setConnection] = useState("connecting"); useEffect(() => { setMessages([]); setConnection("connecting"); const es = new EventSource(messagesUrl(sinceMinutes)); es.onopen = () => { setMessages([]); setConnection("open"); }; es.onmessage = (e) => { let m: SwarmMessage; try { m = JSON.parse(e.data) as SwarmMessage; } catch { return; } setMessages((prev) => newest([...prev, m], MAX_MESSAGES)); }; es.onerror = () => { setConnection( es.readyState === 0 /* CONNECTING */ ? "reconnecting" : "closed", ); }; return () => es.close(); }, [sinceMinutes]); return { messages, connection }; }