onTypingStatusUpdated fires false events

Hey,

I found something odd while testing one of our features in the chat (over GiftedChat ) .

In our code we register on the channel to : channelHandler.onTypingStatusUpdated.

our chat setup, is a group channel with a user and an agent from sendbirdk desk.

I encountered few odd behaviors :

  1. when the agent starting typing we get the event , but some time while typing ( apx. 20 seconds ) we get a status updated for False ?

  2. if the agent types than stop for a minute ( we get a false event as stated in 1. ) , when it continues to typing the event is not updated to true.

are these a known behavior ?

Hi @Ronen_Meiri,

The first behavior is normal, I see this behavior in my demo app. Regarding the second behavior, are your agents utilizing the Sendbird Dashboard to chat with customers or do you have your own JavaScript app?

Hey Ian,

  1. if this a normal behavior, In case I want to indicate to the user when the agent is typing, how can I do that ?
    Is there any other event to register on ?
    Why the false event is fired while the agent is writing?

  2. Our agents are utilizing Sendbird Dashboard chat.

@Ronen_Meiri, thanks for the information. Let me run a couple of tests on my end and I should have an update for you soon.

any updates here? i’m also noticing weird behavior surrounding the typing indicators. Mainly, if a user is typing in my web app in a group channel, and someone in that channel has the mobile app open, but not on their messaging screen, the typing indicator shows indefinitely if they navigate to the messaging screen shortly after. Whereas if they are already on the messaging screen when the typing starts, the typing indicator will go away after a certain timeout when the typing on the web app stops.

This first video illustrates the behavior when the mobile user is on the messaging screen when the typing begins and ends.

This second video illustrates the behavior when the mobile user is away from the messaging screen when the type begins, and then navigates to the messaging screen.


As you can see, the typing indicator never disappears even once the typing has been stopped for the same amount of time as it was in the previous video.

Here is the relevant code for displaying the typing indicator in the app:

export const TypingIndicator: FC = () => {
  const isConnected = useAppSelector(selectIsConnected)
  const [typingUsers, setTypingUsers] = useState<string[]>([])

  useEffect(() => {
    if (!isConnected) return

    const handler = new GroupChannelHandler({
      onTypingStatusUpdated(channel) {
        setTypingUsers(channel.getTypingUsers().map(({ nickname }) => nickname))
      },
    })

    sb.groupChannel.addGroupChannelHandler(
      'TYPING_USERS_CHANNEL_HANDLER',
      handler,
    )

    return () => {
      setTypingUsers([])
      sb.groupChannel.removeGroupChannelHandler('TYPING_USERS_CHANNEL_HANDLER')
    }
  }, [isConnected])

  if (!typingUsers.length) return null

  return (
    <>
      <View style={styles.container}>
        <View style={[styles.dot, { backgroundColor: dotColor[0] }]} />
        <View style={[styles.dot, { backgroundColor: dotColor[1] }]} />
        <View style={[styles.dot, { backgroundColor: dotColor[2] }]} />
      </View>
      <Text style={styles.text}>{typingUsers.join('\n')}</Text>
    </>
  )
}

and the code that triggers the event in the web application

export const MessageInput: React.FC = () => {
  const classes = useStyles()
  const [messageText, setMessageText] = useState('')
  const selectedChannel = useAppSelector(selectSelectedChannel)
  const dispatch = useAppDispatch()

  const hasValidStagedMessage = !!messageText.trim()

  if (!selectedChannel) return null

  const onClick = async () => {
    dispatch(sendMessage({ url: selectedChannel.url, text: messageText }))
    setMessageText('')
    await sendStopTyping()
  }

  const sendStartTyping = useCallback(
    throttle(
      () => {
        sb.groupChannel
          .buildGroupChannelFromSerializedData(selectedChannel)
          .startTyping()
      },
      TYPING_UPDATE_THROTTLE_MS,
      { trailing: false },
    ),
    [],
  )

  const sendStopTyping = async () =>
    await sb.groupChannel
      .buildGroupChannelFromSerializedData(selectedChannel)
      .endTyping()

  return (
    <div className={classes.container}>
      <TextField
        value={messageText}
        multiline
        fullWidth
        size="small"
        variant="outlined"
        placeholder="Type a message"
        InputProps={{
          className: classes.input,
          fullWidth: true,
          endAdornment: (
            <IconButton
              size="small"
              disabled={!selectedChannel || !hasValidStagedMessage}
              onClick={onClick}>
              <SendIcon fontSize="small" />
            </IconButton>
          ),
        }}
        onChange={async event => {
          setMessageText(event.currentTarget.value)
          event.currentTarget.value ? sendStartTyping() : sendStopTyping()
        }}
        onKeyDown={e => {
          if (!e.shiftKey && e.keyCode === 13) {
            e.preventDefault()
            if (!hasValidStagedMessage) return

            onClick()
          }
        }}
      />
    </div>
  )
}

@Ian
I’m experiencing case 1 for the typing action of more than 12 seconds. I wonder why you said the first behavior is normal. Could you give me some references (ex. official doc) related to this behavior if you have one? I could not find one when I read the JS developer doc about group channel event handlers.