Carries the chat's live side, which ChatModal lays over the history it
fetches and the chat buttons show as a badge. WSProvider provides it
through WSChatContext, and components read it with useWSChat. The
socket sends chat only to signed-in users, so for a visitor it stays empty.
Shows chat messages as they arrive. It holds the ones received this
session, at most 200, which ChatModal merges with the history it
fetches. A reconnect empties it while the chat is closed, since ChatModal
fetches everything again on open.
deletedChatIds: Set<string>
Takes the messages deleted this session out of the history ChatModal
fetched.
unreadChatCount: number
Drives the chat buttons' unread badge. It counts the messages from others after the read marker, which the server keeps, so the count agrees across tabs and devices.
chatReadAt: Date | null
Places the "new" divider when the chat opens. It holds the time of the
newest message the user has seen, which the server keeps, and is null
until the welcome, and for a visitor.
Shows who is typing. It includes the user themselves, whom ChatModal
filters out.
sendChatMessage: (body: string,replyTo?: ChatReplyTarget) => void
Trims body and sends it as a pending message. Ignores a blank body.
retryChatMessage: (nonce: string) => void
discardChatMessage: (nonce: string) => void
editChatMessage: (id: string,body: string) => void
Sends the edit if the socket is open, else drops it. It shows once the
server broadcasts it, or fails as chatError.
deleteChatMessage: (id: string) => void
Sends the deletion if the socket is open, as editChatMessage does.
dismissChatError: () => void
markChatRead: (at: Date) => void
Moves the read marker up to at, the time of the newest message seen. It
zeroes unreadChatCount at once and sends the marker at most once a
second. A marker set offline goes out with the next welcome.
reconcileChat: () => void
Repairs the live buffer after a reconnect. It replaces its messages between
from and to with messages, which ChatModal fetched. A message
missing from them was deleted while the socket was down. A failed send
found among them did reach the server, and leaves the pending list.
setChatTyping: (typing: boolean) => void
Tells the server whether the user is typing, when the socket is open.
ChatModal resends true every few seconds while typing continues, since
the server forgets a typer after 6 s.
setChatOpen: (open: boolean) => void
Spares the user a notification for a mention they read live. It tells the server whether the chat is open in a visible tab; while it is, the server sends no notification for a mention, and this client doesn't count the message unread.