11import React , { useMemo } from 'react' ;
2- import { sanitizeUrl } from '@braintree/sanitize-url' ;
32import type { ReactPlayerProps } from 'react-player' ;
43import type { Attachment as StreamAttachment } from 'stream-chat' ;
54
@@ -19,13 +18,15 @@ import {
1918 GalleryContainer ,
2019 ImageContainer ,
2120 MediaContainer ,
21+ UnsupportedAttachmentContainer ,
2222} from './AttachmentContainer' ;
2323
2424import type { AttachmentActionsProps } from './AttachmentActions' ;
2525import type { AudioProps } from './Audio' ;
2626import type { CardProps } from './Card' ;
2727import type { FileAttachmentProps } from './FileAttachment' ;
2828import type { GalleryProps , ImageProps } from '../Gallery' ;
29+ import type { UnsupportedAttachmentProps } from './UnsupportedAttachment' ;
2930import type { ActionHandlerReturnType } from '../Message/hooks/useActionHandler' ;
3031
3132import type { DefaultStreamChatGenerics } from '../../types/types' ;
@@ -35,6 +36,7 @@ const CONTAINER_MAP = {
3536 card : CardContainer ,
3637 file : FileContainer ,
3738 media : MediaContainer ,
39+ unsupported : UnsupportedAttachmentContainer ,
3840} as const ;
3941
4042export const ATTACHMENT_GROUPS_ORDER = [
@@ -44,6 +46,7 @@ export const ATTACHMENT_GROUPS_ORDER = [
4446 'media' ,
4547 'audio' ,
4648 'file' ,
49+ 'unsupported' ,
4750] as const ;
4851
4952export type AttachmentProps <
@@ -67,6 +70,8 @@ export type AttachmentProps<
6770 Image ?: React . ComponentType < ImageProps > ;
6871 /** Custom UI component for displaying a media type attachment, defaults to `ReactPlayer` from 'react-player' */
6972 Media ?: React . ComponentType < ReactPlayerProps > ;
73+ /** Custom UI component for displaying unsupported attachment types, defaults to NullComponent */
74+ UnsupportedAttachment ?: React . ComponentType < UnsupportedAttachmentProps > ;
7075} ;
7176
7277/**
@@ -97,41 +102,40 @@ const renderGroupedAttachments = <
97102 attachments,
98103 ...rest
99104} : AttachmentProps < StreamChatGenerics > ) : GroupedRenderedAttachment => {
100- const uploadedImages : StreamAttachment < StreamChatGenerics > [ ] = [ ] ;
101-
102- const containers = attachments . reduce < GroupedRenderedAttachment > (
103- ( acc , attachment ) => {
104- if ( isUploadedImage ( attachment ) ) {
105- uploadedImages . push ( {
106- ...attachment ,
107- image_url : sanitizeUrl ( attachment . image_url ) ,
108- thumb_url : sanitizeUrl ( attachment . thumb_url ) ,
109- } ) ;
110- } else {
105+ const uploadedImages : StreamAttachment < StreamChatGenerics > [ ] = attachments . filter ( ( attachment ) =>
106+ isUploadedImage ( attachment ) ,
107+ ) ;
108+
109+ const containers = attachments
110+ . filter ( ( attachment ) => ! isUploadedImage ( attachment ) )
111+ . reduce < GroupedRenderedAttachment > (
112+ ( typeMap , attachment ) => {
111113 const attachmentType = getAttachmentType ( attachment ) ;
112114
113- if ( attachmentType ) {
114- const Container = CONTAINER_MAP [ attachmentType ] ;
115- acc [ attachmentType ] . push (
116- < Container
117- key = { `${ attachmentType } -${ acc [ attachmentType ] . length } ` }
118- { ...rest }
119- attachment = { attachment }
120- /> ,
121- ) ;
122- }
123- }
124- return acc ;
125- } ,
126- {
127- audio : [ ] ,
128- card : [ ] ,
129- file : [ ] ,
130- gallery : [ ] ,
131- image : [ ] ,
132- media : [ ] ,
133- } ,
134- ) ;
115+ const Container = CONTAINER_MAP [ attachmentType ] ;
116+ typeMap [ attachmentType ] . push (
117+ < Container
118+ key = { `${ attachmentType } -${ typeMap [ attachmentType ] . length } ` }
119+ { ...rest }
120+ attachment = { attachment }
121+ /> ,
122+ ) ;
123+
124+ return typeMap ;
125+ } ,
126+ {
127+ audio : [ ] ,
128+ card : [ ] ,
129+ file : [ ] ,
130+ media : [ ] ,
131+ unsupported : [ ] ,
132+ // not used in reduce
133+ // eslint-disable-next-line sort-keys
134+ image : [ ] ,
135+ // eslint-disable-next-line sort-keys
136+ gallery : [ ] ,
137+ } ,
138+ ) ;
135139
136140 if ( uploadedImages . length > 1 ) {
137141 containers [ 'gallery' ] = [
@@ -149,14 +153,15 @@ const renderGroupedAttachments = <
149153 < ImageContainer key = 'image-container' { ...rest } attachment = { uploadedImages [ 0 ] } /> ,
150154 ] ;
151155 }
156+
152157 return containers ;
153158} ;
154159
155160const getAttachmentType = <
156161 StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics
157162> (
158163 attachment : AttachmentProps < StreamChatGenerics > [ 'attachments' ] [ number ] ,
159- ) : keyof typeof CONTAINER_MAP | null => {
164+ ) : keyof typeof CONTAINER_MAP => {
160165 if ( isScrapedContent ( attachment ) ) {
161166 return 'card' ;
162167 } else if ( isMediaAttachment ( attachment ) ) {
@@ -167,5 +172,5 @@ const getAttachmentType = <
167172 return 'file' ;
168173 }
169174
170- return null ;
175+ return 'unsupported' ;
171176} ;
0 commit comments