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.to- Recipient JID (user or group)state: ChatActivity- Type of chat state to send
Result<(), ChatStateError>;Ok(())on success; aChatStateErrorif the client is disconnected or the JID is invalid
send_composing
Convenience method to send typing indicator.send_recording
Convenience method to send audio recording indicator.send_paused
Convenience method to send paused/stopped typing indicator.Receiving chat state events
ChatStateEvent
Incoming chatstate stanzas (typing indicators from other users) are dispatched asChatStateEvent 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.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)
<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 returnResult<(), 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
- Throttle updates: Don’t send chat state updates more than once every 2-3 seconds
- Clear on send: Send
ChatActivity::Idlebefore sending the actual message - Auto-timeout: Consider auto-clearing typing indicators after 10-15 seconds of inactivity
- Don’t spam: Only send when state actually changes
- Groups: Be mindful that all group members will see the indicator
Complete Example
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.