Typing Indicators

Overview

This guide covers text typing indicators within a conversation.

Before you begin, make sure you added the SDK to your app and you are able to create a conversation.

NOTE: A step-by-step tutorial to build a chat application is available here.

This guide will make use of the following concepts:

Typing Indicators

Typing Indicators are used to notify conversation members on whether or not a member is currently typing a text message.

Send typing state events

Set the Member's current typing (on/off) state when they start or stop typing a text message:

// call this when a member starts typing
conversation.startTyping();

// call this when a member stops typing
conversation.stopTyping();
// call this when a member starts typing
conversation.startTyping()

// call this when a member stops typing
conversation.stopTyping()
// call this when a member starts typing
conversation.startTyping();

// call this when a member stops typing
conversation.stopTyping();
conversation.sendStartTyping(completionHandler:)
conversation.sendStopTyping(completionHandler:)
// call this when a member starts typing
[conversation sendStartTyping:^(NSError * _Nullable error) completionHandler];

// call this when a member stops typing
[conversation sendStopTyping:^(NSError * _Nullable error) completionHandler];

Listen for the state of other members

The following will listen for the typing (on/off) events created by the above calls:

conversation.on('text:typing:on', (event) => {
  console.log(event.user.name + " is typing");
});

conversation.on("text:typing:off", (event) => {
  console.log(event.user.name + " stopped typing");
});
// Option 1: Listen for typing events using NexmoTypingEventListener
conversation.addTypingEventListener(typingEventListener)

// or

// Option 2: Listen for typing events using NexmoMessageEventListener
conversation.addMessageEventListener(messageListener)

private val typingEventListener = NexmoTypingEventListener { typingEvent ->
    val typingState = if(typingEvent?.state == NexmoTypingState.ON) "typing" else "not typing"
    Timber.d("User ${typingEvent.fromMemberId} is $typingState")
}

private val messageListener = object : NexmoMessageEventListener {
    override fun onTypingEvent(typingEvent: NexmoTypingEvent) {
        val typingState = if(typingEvent.state == NexmoTypingState.ON) "typing" else "not typing"
        Log.d("TAG", "User ${typingEvent.fromMemberId} is $typingState")
    }

    override fun onAttachmentEvent(attachmentEvent: NexmoAttachmentEvent) {}

    override fun onTextEvent(textEvent: NexmoTextEvent) {}

    override fun onSeenReceipt(seenEvent: NexmoSeenEvent) {}

    override fun onEventDeleted(deletedEvent: NexmoDeletedEvent) {}

    override fun onDeliveredReceipt(deliveredEvent: NexmoDeliveredEvent) {}
}
// Option 1: Listen for typing events using NexmoTypingEventListener
conversation.addTypingEventListener(typingEventListener);

// or

// Option 2: Listen for typing events using NexmoMessageEventListener
conversation.addMessageEventListener(messageListener);

private NexmoTypingEventListener typingEventListener = new NexmoTypingEventListener() {
    @Override
    public void onTyping(NexmoTypingEvent typingEvent) {
        String typingState;

        if (typingEvent.getState() == NexmoTypingState.ON) {
            typingState = "typing";
        } else {
            typingState = "not typing";
        }

        Timber.d("User " + typingEvent.getFromMemberId() + " is " + typingState);
    }
};

private NexmoMessageEventListener messageListener = new NexmoMessageEventListener() {
    @Override
    public void onTypingEvent(@NonNull NexmoTypingEvent typingEvent) {
        String typingState;

        if (typingEvent.getState() == NexmoTypingState.ON) {
            typingState = "typing";
        } else {
            typingState = "not typing";
        }

        Log.d("TAG", "User " + typingEvent.getFromMemberId() + " is " + typingState);
    }

    @Override
    public void onTextEvent(@NonNull NexmoTextEvent textEvent) {}

    @Override
    public void onAttachmentEvent(@NonNull NexmoAttachmentEvent attachmentEvent) {}

    @Override
    public void onEventDeleted(@NonNull NexmoDeletedEvent deletedEvent) {}

    @Override
    public void onSeenReceipt(@NonNull NexmoSeenEvent seenEvent) {}

    @Override
    public void onDeliveredReceipt(@NonNull NexmoDeliveredEvent deliveredEvent) {}
};

Add NXMConversationDelegate as an extension to a ViewController or similar, and implement conversation(_ conversation: NXMConversation, didReceive event: NXMTextTypingEvent):

Note: The first method below is required when implementing NXMConversationDelegate:

extension ViewController: NXMConversationDelegate {
    func conversation(_ conversation: NXMConversation, didReceive error: Error) {
        NSLog("Conversation error: \(error.localizedDescription)")
    }
    func conversation(_ conversation: NXMConversation, didReceive event: NXMTextTypingEvent) {
        if event.status == .on {
            NSLog("Started typing")
        } else {
            NSLog("Typing ended")
        }
    }
}

Have a ViewController, or similar, conform to NXMConversationDelegate and implement conversation:didReceiveTypingEvent::

Note: The first method below is required when implementing NXMConversationDelegate:

- (void)conversation:(NXMConversation *)conversation didReceive:(NSError *)error {
    NSLog(@"Conversation error: %@", error.localizedDescription);
}
- (void)conversation:(NXMConversation *)conversation didReceiveTypingEvent:(NXMTextTypingEvent *)event {
    if (event.status == NXMTextTypingEventStatusOn) {
        NSLog(@"Started typing");
    } else {
        NSLog(@"Typing ended");
    }
}

Reference