UNPKG

stream-chat-react

Version:

React components to create chat conversations or livestream style chat

95 lines (94 loc) 3.7 kB
import React, { useMemo } from 'react'; import { isAudioAttachment, isFileAttachment, isImageAttachment, isScrapedContent, isSharedLocationResponse, isVideoAttachment, isVoiceRecordingAttachment, } from 'stream-chat'; import { AudioContainer, CardContainer, FileContainer, GalleryContainer, GeolocationContainer, ImageContainer, MediaContainer, UnsupportedAttachmentContainer, VoiceRecordingContainer, } from './AttachmentContainer'; import { SUPPORTED_VIDEO_FORMATS } from './utils'; const CONTAINER_MAP = { audio: AudioContainer, card: CardContainer, file: FileContainer, media: MediaContainer, unsupported: UnsupportedAttachmentContainer, voiceRecording: VoiceRecordingContainer, }; export const ATTACHMENT_GROUPS_ORDER = [ 'card', 'gallery', 'image', 'media', 'audio', 'voiceRecording', 'file', 'geolocation', 'unsupported', ]; /** * A component used for rendering message attachments. By default, the component supports: AttachmentActions, Audio, Card, File, Gallery, Image, and Video */ export const Attachment = (props) => { const { attachments } = props; const groupedAttachments = useMemo(() => renderGroupedAttachments(props), // eslint-disable-next-line react-hooks/exhaustive-deps [attachments]); return (React.createElement("div", { className: 'str-chat__attachment-list' }, ATTACHMENT_GROUPS_ORDER.reduce((acc, groupName) => [...acc, ...groupedAttachments[groupName]], []))); }; const renderGroupedAttachments = ({ attachments, ...rest }) => { const uploadedImages = attachments.filter((attachment) => isImageAttachment(attachment)); const containers = attachments .filter((attachment) => !isImageAttachment(attachment)) .reduce((typeMap, attachment) => { if (isSharedLocationResponse(attachment)) { typeMap.geolocation.push(React.createElement(GeolocationContainer, { ...rest, key: 'geolocation-container', location: attachment })); } else { const attachmentType = getAttachmentType(attachment); const Container = CONTAINER_MAP[attachmentType]; typeMap[attachmentType].push(React.createElement(Container, { key: `${attachmentType}-${typeMap[attachmentType].length}`, ...rest, attachment: attachment })); } return typeMap; }, { audio: [], card: [], file: [], media: [], unsupported: [], // not used in reduce // eslint-disable-next-line sort-keys image: [], // eslint-disable-next-line sort-keys gallery: [], geolocation: [], voiceRecording: [], }); if (uploadedImages.length > 1) { containers['gallery'] = [ React.createElement(GalleryContainer, { key: 'gallery-container', ...rest, attachment: { images: uploadedImages, type: 'gallery', } }), ]; } else if (uploadedImages.length === 1) { containers['image'] = [ React.createElement(ImageContainer, { key: 'image-container', ...rest, attachment: uploadedImages[0] }), ]; } return containers; }; const getAttachmentType = (attachment) => { if (isScrapedContent(attachment)) { return 'card'; } else if (isVideoAttachment(attachment, SUPPORTED_VIDEO_FORMATS)) { return 'media'; } else if (isAudioAttachment(attachment)) { return 'audio'; } else if (isVoiceRecordingAttachment(attachment)) { return 'voiceRecording'; } else if (isFileAttachment(attachment, SUPPORTED_VIDEO_FORMATS)) { return 'file'; } return 'unsupported'; };