stream-chat-react
Version:
React components to create chat conversations or livestream style chat
60 lines (59 loc) • 2.89 kB
JavaScript
import React from 'react';
import clsx from 'clsx';
import { useChannelStateContext } from '../../context/ChannelStateContext';
import { useChatContext } from '../../context/ChatContext';
import { useTypingContext } from '../../context/TypingContext';
import { useTranslationContext } from '../../context/TranslationContext';
const useJoinTypingUsers = (names) => {
const { t } = useTranslationContext();
if (!names.length)
return null;
const [name, ...rest] = names;
if (names.length === 1)
return t('{{ user }} is typing...', {
user: name,
});
const MAX_JOINED_USERS = 3;
if (names.length > MAX_JOINED_USERS)
return t('{{ users }} and more are typing...', {
users: names.slice(0, MAX_JOINED_USERS).join(', ').trim(),
});
return t('{{ users }} and {{ user }} are typing...', {
user: name,
users: rest.join(', ').trim(),
});
};
/**
* TypingIndicator lists users currently typing, it needs to be a child of Channel component
*/
const UnMemoizedTypingIndicator = (props) => {
const { threadList } = props;
const { channelConfig, thread } = useChannelStateContext('TypingIndicator');
const { client } = useChatContext('TypingIndicator');
const { typing = {} } = useTypingContext('TypingIndicator');
const typingInChannel = !threadList
? Object.values(typing).filter(({ parent_id, user }) => user?.id !== client.user?.id && !parent_id)
: [];
const typingInThread = threadList
? Object.values(typing).filter(({ parent_id, user }) => user?.id !== client.user?.id && parent_id === thread?.id)
: [];
const typingUserList = (threadList ? typingInThread : typingInChannel)
.map(({ user }) => user?.name || user?.id)
.filter(Boolean);
const joinedTypingUsers = useJoinTypingUsers(typingUserList);
const isTypingActive = (threadList && typingInThread.length) || (!threadList && typingInChannel.length);
if (channelConfig?.typing_events === false) {
return null;
}
if (!isTypingActive)
return null;
return (React.createElement("div", { className: clsx('str-chat__typing-indicator', {
'str-chat__typing-indicator--typing': isTypingActive,
}), "data-testid": 'typing-indicator' },
React.createElement("div", { className: 'str-chat__typing-indicator__dots' },
React.createElement("span", { className: 'str-chat__typing-indicator__dot' }),
React.createElement("span", { className: 'str-chat__typing-indicator__dot' }),
React.createElement("span", { className: 'str-chat__typing-indicator__dot' })),
React.createElement("div", { className: 'str-chat__typing-indicator__users', "data-testid": 'typing-users' }, joinedTypingUsers)));
};
export const TypingIndicator = React.memo(UnMemoizedTypingIndicator);