Skip to main content
The Chatstate struct provides methods for sending typing indicators and recording notifications to recipients.

Access

Access chatstate operations through the client:

Methods

send

Send a chat state update to a recipient.
Parameters:
  • to - Recipient JID (user or group)
  • state: ChatActivity - Type of chat state to send
Returns:
  • Result<(), ChatStateError>; Ok(()) on success; a ChatStateError if the client is disconnected or the JID is invalid
Example:

send_composing

Convenience method to send typing indicator.
Example:

send_recording

Convenience method to send audio recording indicator.
Example:

send_paused

Convenience method to send paused/stopped typing indicator.
Example:

Receiving chat state events

ChatStateEvent

Incoming chatstate stanzas (typing indicators from other users) are dispatched as ChatStateEvent values. Register a handler with subscribe_chatstate_handler to receive them.
Jid
The chat where the event occurred. For direct messages this is the sender’s JID; for groups this is the group JID.
Option<Jid>
For group chats, the participant who triggered the event. None for 1:1 chats.
ChatActivity
The parsed chat state; see ChatActivity below.
Example:

ChatActivity

Use the same activity value for incoming events and outgoing updates.
ChatActivity is #[non_exhaustive], so match statements should include a wildcard arm. Wire format mapping:

Activity representation

Persisted event JSON changes intentionally. See the before/after migration examples before updating external consumers. ChatActivity is shared by sending, ChatStateEvent.state, and ChatPresenceUpdate.state. It describes activity in one chat. Global online/offline availability uses PresenceStatus separately. Serde serializes the activities as "typing", "recording_audio", and "idle". These names are semantic values. Use into_child_node() and from_child_node(&NodeRef) for the protocol projection. Recording audio produces <composing media="audio"/>. The parser treats unknown media on composing as typing and unknown child tags as idle. Keep the raw node separately if you need to preserve unknown attributes.

Wire Format

Composing (Typing)

Recording (Voice)

Note: Recording uses <composing media="audio"> rather than a separate tag.

Paused (Stopped)

Usage Patterns

Typing indicator lifecycle

Recording Audio

Throttling

To avoid spamming chat state updates:

Group Chats

Chat state indicators work in group chats as well:

Error Handling

All methods return Result<(), ChatStateError>. You’ll encounter these most often:
  • Not connected; you are not connected to WhatsApp
  • Invalid JID; the recipient JID is malformed
  • Network errors; connection dropped mid-send

Best Practices

  1. Throttle updates: Don’t send chat state updates more than once every 2-3 seconds
  2. Clear on send: Send ChatActivity::Idle before sending the actual message
  3. Auto-timeout: Consider auto-clearing typing indicators after 10-15 seconds of inactivity
  4. Don’t spam: Only send when state actually changes
  5. Groups: Be mindful that all group members will see the indicator

Complete Example

Retain subscription while receiving chatstate updates. Dropping it unregisters the handler; an in-flight dispatch can still complete. client.chatstate().subscribe_handler(handler) follows the same Subscription contract.