// The JS client keeps track of the typing state for you. // Just call `channel.keystroke()` when the user types and // `channel.stopTyping()` when the user sends the message (or aborts) // sends a typing.start event at most once every two seconds await channel.keystroke(); // sends a typing.start event for a particular thread await channel.keystroke(thread_id); // sends the typing.stop event await channel.stopTyping();Typing Indicators
If you use Stream’s UI components, typing indicators are automatically handled. The typing indicators can be turned on or off in the channel type settings. This example below shows how to integrate typing indicators into your own message input UI.
Sending Typing Events
When a user starts typing call the keystroke method. Optionally you can specify a thread id to have a thread specific typing indicator. A few seconds after a user stops typing use stopTyping.
// The Dart client keeps track of the typing state for you. // Just call `channel.keystroke()` when the user types and // `channel.stopTyping()` when the user sends the message (or aborts) // sends a typing.start event at most once every two seconds await channel.keystroke(); // sends a typing.start event for a particular thread await channel.keystroke(thread_id); // sends the typing.stop event await channel.stopTyping();// Sends a typing.start event at most once every two seconds channelClient.keystroke().enqueue() // Sends a typing.start event for a particular thread channelClient.keystroke(parentId = "threadId").enqueue() // Sends the typing.stop event channelClient.stopTyping().enqueue()// Automatically// The Swift client keeps track of the typing state for you. // Just call `sendKeystrokeEvent()` when the user types and // sends a typing.start event at most once every two seconds // automatically sends typingStop event after 15 seconds let channelController = client.channelController(for: .init(type: .messaging, id: "general")) // automatically channelController.sendKeystrokeEvent() // or manually channelController.sendStartTypingEvent() channelController.sendStopTypingEvent()// The Unreal SDK keeps track of the typing state for you. // Just call `Channel->Keystroke()` when the user types and // `Channel->StopTyping()` when the user sends the message (or aborts) // Sends a typing.start event at most once every two seconds, // and a typing.stop event two seconds after the last keystroke Channel->KeyStroke(); // Manually sends the typing.stop event, and cancels any pending // typing.stop event queued by Keystroke() Channel->StopTyping();// Sends a typing.start event channelClient.keystroke().enqueue(); // Sends a typing.start event for a particular thread channelClient.keystroke("threadId").enqueue(); // Sends the typing.stop event channelClient.stopTyping().enqueue();// Send typing started event await channel.SendTypingStartedEventAsync(); // Send typing stopped event await channel.SendTypingStoppedEventAsync();Receiving typing indicator events
Listening to typing indicators uses the event system, an example is shown below
// channels keep track of the users that are currently typing. // `channel.state.typing` is an immutable object which gets regenerated // every time a new user is added or removed to this list console.log(channel.state.typing); // start typing event handling channel.on("typing.start", (event) => { if (event.parent_id) { console.log( `${event.user.name} started typing in thread ${event.parent_id}`, ); } else { console.log(`${event.user.name} started typing`); } }); // stop typing event handling channel.on("typing.stop", (event) => { if (event.parent_id) { console.log( `${event.user.name} stopped typing in thread ${event.parent_id}`, ); } else { console.log(`${event.user.name} stopped typing`); } });// channels keep track of the users that are currently typing // the `channel.state.typingEvents` is an immutable object which gets regenerated // every time a new user is added or removed to this list print(channel.state.typingEvents); // add typing start event handling channel.on('typing.start', (event) => { print('${event.user.name} started typing'); }); // add typing stop event handling channel.on('typing.stop', event => { print('${event.user.name} stopped typing'); });// Add typing start event handling channelClient.subscribeFor<TypingStartEvent> { typingStartEvent -> // Handle event } // Add typing stop event handling channelClient.subscribeFor<TypingStopEvent> { typingStopEvent -> // Handle event }let channelController = client.channelController(for: .init(type: .messaging, id: "general")) class ChannelDelegate: ChatChannelControllerDelegate { func channelController(_ channelController: ChatChannelController, didChangeTypingUsers typingUsers: Set<ChatUser>) { // handle new typing users } } channelController.delegate = ChannelDelegate() channelController.synchronize()// You can manually subscribe to the typing channel events Channel->On<FTypingStartEvent>(this, &UMyWidget::OnTypingStart); Channel->On<FTypingStopEvent>(this, &UMyWidget::OnTypingStop); // Alternatively you can bind to the OnTypingIndicator delegate (also from Blueprints) Channel->OnTypingIndicator.AddDynamic(this, &UMyWidget::OnTypingIndicator);// Add typing start event handling channelClient.subscribeFor( new Class[]{TypingStartEvent.class}, event -> { // Handle change } ); // Add typing stop event handling channelClient.subscribeFor( new Class[]{TypingStopEvent.class}, event -> { // Handle change } );public async Task ReceivingTypingEvents() { var channel = await Client.GetOrCreateChannelWithIdAsync(ChannelType.Messaging, "channel-id"); channel.UserStartedTyping += OnUserStartedTyping; channel.UserStoppedTyping += OnUserStoppedTyping; } private void OnUserStartedTyping(IStreamChannel channel, IStreamUser user) { } private void OnUserStoppedTyping(IStreamChannel channel, IStreamUser user) { }Because clients might fail at sending typing.stop event all Chat clients periodically prune the list of typing users.
Typing Privacy Settings
Please take into account that typing.start and typing.stop events delivery can be controlled by user privacy settings:
// user object with privacy settings where typing indicators are disabled { // other user fields "privacy_settings": { "typing_indicators": { "enabled": false } } }If privacy_settings.typing_indicators.enabled is set to false, then typing.start and typing.stop events will be ignored for this user by Stream’s server and these events will not be sent to other users. In other words other users will not know that the current user was typing.