stream-chat-react
Version:
React components to create chat conversations or livestream style chat
85 lines (84 loc) • 4.31 kB
JavaScript
import throttle from 'lodash.throttle';
import React, { useEffect, useMemo, useState } from 'react';
import { ChannelPreviewMessenger } from './ChannelPreviewMessenger';
import { useIsChannelMuted } from './hooks/useIsChannelMuted';
import { useChannelPreviewInfo } from './hooks/useChannelPreviewInfo';
import { getLatestMessagePreview as defaultGetLatestMessagePreview } from './utils';
import { useChatContext } from '../../context/ChatContext';
import { useTranslationContext } from '../../context/TranslationContext';
import { useMessageDeliveryStatus } from './hooks/useMessageDeliveryStatus';
export const ChannelPreview = (props) => {
const { active, channel, channelUpdateCount, getLatestMessagePreview = defaultGetLatestMessagePreview, Preview = ChannelPreviewMessenger, } = props;
const { channel: activeChannel, client, isMessageAIGenerated, setActiveChannel, } = useChatContext('ChannelPreview');
const { t, userLanguage } = useTranslationContext('ChannelPreview');
const { displayImage, displayTitle, groupChannelDisplayInfo } = useChannelPreviewInfo({
channel,
});
const [lastMessage, setLastMessage] = useState(channel.state.messages[channel.state.messages.length - 1]);
const [unread, setUnread] = useState(0);
const { messageDeliveryStatus } = useMessageDeliveryStatus({
channel,
lastMessage,
});
const isActive = typeof active === 'undefined' ? activeChannel?.cid === channel.cid : active;
const { muted } = useIsChannelMuted(channel);
useEffect(() => {
const handleEvent = (event) => {
if (!event.cid)
return setUnread(0);
if (channel.cid === event.cid)
setUnread(0);
};
client.on('notification.mark_read', handleEvent);
return () => client.off('notification.mark_read', handleEvent);
}, [channel, client]);
useEffect(() => {
const handleEvent = (event) => {
if (channel.cid !== event.cid)
return;
if (event.user?.id !== client.user?.id)
return;
setUnread(channel.countUnread());
};
channel.on('notification.mark_unread', handleEvent);
return () => {
channel.off('notification.mark_unread', handleEvent);
};
}, [channel, client]);
const refreshUnreadCount = useMemo(() => throttle(() => {
if (muted) {
setUnread(0);
}
else {
setUnread(channel.countUnread());
}
}, 400), [channel, muted]);
useEffect(() => {
refreshUnreadCount();
const handleEvent = (event) => {
const deletedMessagesInAnotherChannel = event.type === 'user.messages.deleted' && event.cid && event.cid !== channel.cid;
if (deletedMessagesInAnotherChannel)
return;
setLastMessage(channel.state.latestMessages[channel.state.latestMessages.length - 1]);
refreshUnreadCount();
};
channel.on('message.new', handleEvent);
channel.on('message.updated', handleEvent);
channel.on('message.deleted', handleEvent);
client.on('user.messages.deleted', handleEvent);
channel.on('message.undeleted', handleEvent);
channel.on('channel.truncated', handleEvent);
return () => {
channel.off('message.new', handleEvent);
channel.off('message.updated', handleEvent);
channel.off('message.deleted', handleEvent);
client.off('user.messages.deleted', handleEvent);
channel.off('message.undeleted', handleEvent);
channel.off('channel.truncated', handleEvent);
};
}, [channel, client, refreshUnreadCount, channelUpdateCount]);
if (!Preview)
return null;
const latestMessagePreview = getLatestMessagePreview(channel, t, userLanguage, isMessageAIGenerated);
return (React.createElement(Preview, { ...props, active: isActive, displayImage: displayImage, displayTitle: displayTitle, groupChannelDisplayInfo: groupChannelDisplayInfo, lastMessage: lastMessage, latestMessage: latestMessagePreview, latestMessagePreview: latestMessagePreview, messageDeliveryStatus: messageDeliveryStatus, setActiveChannel: setActiveChannel, unread: unread }));
};