Livqeno Docs

Chat Events

Every event a ChatClient emits, with its payload and when it fires.

ChatClient is a typed event emitter. These 14 events are its whole surface — from ChatEventMap in @ravenkash/chat.

const unsubscribe = chat.on('message', (message) => {
  render(message.senderId, message.text);
});
 
unsubscribe();      // idempotent — calling it twice is safe

chat.on() returns an unsubscribe function, which is deliberately different from room.on() in @ravenkash/rtc (that one returns the room so calls chain). Chat handlers are usually registered inside a component effect, where cleanup is the common path and a mismatched off(event, handler) is the classic way to leak one. chat.off() still exists if you prefer it.

Messages

EventPayloadFires when
messagemessage: ChatMessageA message arrives — including your own, echoed with its canonical id
messageUpdatedmessage: ChatMessageA message was edited
messageDeletedevent: MessageDeletedEventA message was soft-deleted

You receive your own messages back on purpose. sendMessage() resolving is the durability signal; this event is the fan-out. Render from the event and every participant, sender included, shows the same server-assigned order rather than a locally-guessed one.

Reactions

EventPayloadFires when
reactionAddedevent: ReactionEventSomeone reacted
reactionRemovedevent: ReactionEventA reaction was removed

Both are idempotent server-side, so a double-tap on a flaky connection is harmless. See Reactions.

Ephemeral state

EventPayloadFires when
typingevent: TypingEventSomeone's typing state changed
presenceevent: PresenceEventSomeone's online state changed
readevent: ReadReceiptEventA read position advanced

None of these is persisted. Presence goes offline by TTL expiry rather than by an explicit message — which is why a crashed browser shows as offline within 45 seconds instead of never.

You do not receive an echo of your own read. Use the value markAsRead() returns rather than waiting for an event that will not come.

Connection

EventPayloadFires when
connectionStateChangedstate: ChatConnectionStateThe socket's state changed
connectedconnect() finished
disconnectedThe connection dropped, deliberately or not
reconnectingattempt: numberAn automatic reconnect is in progress
reconnectedRecovery succeeded

reconnecting carries the attempt number, unlike RTC's — useful for "still trying (3)" copy.

Errors

EventPayload
errorerror: RavenChatError
import { isRavenChatError } from '@ravenkash/chat';
 
chat.on('error', (error) => {
  if (!isRavenChatError(error)) return;
  if (error.code === 'TOKEN_EXPIRED') refreshToken();
  if (error.code === 'RATE_LIMITED') backOff(error.retryAfterSeconds);
});

An unrecognised code from a newer server arrives as a base RavenChatError with the code preserved, so an older client keeps working across a server upgrade.

These map onto the wire

Each event is the decoded, typed form of a server frame. message is the message frame, typing is typing.started/typing.stopped collapsed into one event with a boolean. If you need the frame level — for a client in a language Livqeno does not ship — see WebSocket protocol.

Other platforms

const { messages, send, loadMore, hasMore } = useMessages();
const { typingUsers, onInput } = useTyping();
const presence = usePresence();
const state = useChatConnectionState();
const error = useChatError();

Next steps