Skip to content

Commit 6e5635d

Browse files
v10.7.0
v10.7.0
2 parents dc9139f + af5b39f commit 6e5635d

File tree

8 files changed

+94
-45
lines changed

8 files changed

+94
-45
lines changed

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,5 @@ jobs:
2727
- name: Release
2828
env:
2929
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
30-
GH_TOKEN: ${{ secrets.GH_TOKEN }}
30+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
3131
run: yarn semantic-release

src/components/Attachment/Attachment.tsx

Lines changed: 41 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import React, { useMemo } from 'react';
2-
import { sanitizeUrl } from '@braintree/sanitize-url';
32
import type { ReactPlayerProps } from 'react-player';
43
import 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

2424
import type { AttachmentActionsProps } from './AttachmentActions';
2525
import type { AudioProps } from './Audio';
2626
import type { CardProps } from './Card';
2727
import type { FileAttachmentProps } from './FileAttachment';
2828
import type { GalleryProps, ImageProps } from '../Gallery';
29+
import type { UnsupportedAttachmentProps } from './UnsupportedAttachment';
2930
import type { ActionHandlerReturnType } from '../Message/hooks/useActionHandler';
3031

3132
import 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

4042
export 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

4952
export 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

155160
const 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
};

src/components/Attachment/AttachmentContainer.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { Audio as DefaultAudio } from './Audio';
99
import { Gallery as DefaultGallery, ImageComponent as DefaultImage } from '../Gallery';
1010
import { Card as DefaultCard } from './Card';
1111
import { FileAttachment as DefaultFile } from './FileAttachment';
12+
import { NullComponent as DefaultUnsupportedAttachment } from './UnsupportedAttachment';
1213
import {
1314
AttachmentContainerProps,
1415
isGalleryAttachmentType,
@@ -292,3 +293,14 @@ export const MediaContainer = <
292293
</AttachmentWithinContainer>
293294
);
294295
};
296+
297+
export const UnsupportedAttachmentContainer = <
298+
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics
299+
>({
300+
attachment,
301+
UnsupportedAttachment = DefaultUnsupportedAttachment,
302+
}: RenderAttachmentProps<StreamChatGenerics>) => (
303+
<>
304+
<UnsupportedAttachment attachment={attachment} />
305+
</>
306+
);
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import React from 'react';
2+
import type { Attachment } from 'stream-chat';
3+
import type { DefaultStreamChatGenerics } from '../../types/types';
4+
5+
export type UnsupportedAttachmentProps<
6+
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics
7+
> = {
8+
attachment: Attachment<StreamChatGenerics>;
9+
};
10+
11+
export const UnsupportedAttachment = <
12+
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics
13+
>({
14+
attachment,
15+
}: UnsupportedAttachmentProps<StreamChatGenerics>) => (
16+
<div>
17+
<div>
18+
Unsupported attachment type <strong>{attachment.type ?? 'unknown'}</strong>
19+
</div>
20+
<code>{JSON.stringify(attachment, null, 4)}</code>;
21+
</div>
22+
);
23+
24+
export const NullComponent = () => null;

src/components/Attachment/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@ export * from './AttachmentActions';
33
export * from './AttachmentContainer';
44
export * from './Audio';
55
export * from './Card';
6+
export * from './UnsupportedAttachment';
67
export * from './FileAttachment';
78
export * from './utils';

src/components/Gallery/Gallery.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import React, { CSSProperties, MutableRefObject, useState } from 'react';
2+
import { sanitizeUrl } from '@braintree/sanitize-url';
23
import clsx from 'clsx';
34

45
import { Modal } from '../Modal';
@@ -81,7 +82,7 @@ const UnMemoizedGallery = <
8182
>
8283
<img
8384
alt='User uploaded content'
84-
src={image.previewUrl || image.image_url || image.thumb_url}
85+
src={sanitizeUrl(image.previewUrl || image.image_url || image.thumb_url)}
8586
style={image.style}
8687
{...(innerRefs?.current && { ref: (r) => (innerRefs.current[i] = r) })}
8788
/>

src/components/Gallery/__tests__/__snapshots__/Gallery.test.js.snap

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ exports[`Gallery should render component with 3 images 1`] = `
1111
>
1212
<img
1313
alt="User uploaded content"
14+
src="about:blank"
1415
/>
1516
</button>
1617
<button
@@ -20,6 +21,7 @@ exports[`Gallery should render component with 3 images 1`] = `
2021
>
2122
<img
2223
alt="User uploaded content"
24+
src="about:blank"
2325
/>
2426
</button>
2527
<button
@@ -29,6 +31,7 @@ exports[`Gallery should render component with 3 images 1`] = `
2931
>
3032
<img
3133
alt="User uploaded content"
34+
src="about:blank"
3235
/>
3336
</button>
3437
</div>
@@ -45,6 +48,7 @@ exports[`Gallery should render component with 4 images 1`] = `
4548
>
4649
<img
4750
alt="User uploaded content"
51+
src="about:blank"
4852
/>
4953
</button>
5054
<button
@@ -54,6 +58,7 @@ exports[`Gallery should render component with 4 images 1`] = `
5458
>
5559
<img
5660
alt="User uploaded content"
61+
src="about:blank"
5762
/>
5863
</button>
5964
<button
@@ -63,6 +68,7 @@ exports[`Gallery should render component with 4 images 1`] = `
6368
>
6469
<img
6570
alt="User uploaded content"
71+
src="about:blank"
6672
/>
6773
</button>
6874
<button
@@ -72,6 +78,7 @@ exports[`Gallery should render component with 4 images 1`] = `
7278
>
7379
<img
7480
alt="User uploaded content"
81+
src="about:blank"
7582
/>
7683
</button>
7784
</div>
@@ -88,6 +95,7 @@ exports[`Gallery should render component with 5 images 1`] = `
8895
>
8996
<img
9097
alt="User uploaded content"
98+
src="about:blank"
9199
/>
92100
</button>
93101
<button
@@ -97,6 +105,7 @@ exports[`Gallery should render component with 5 images 1`] = `
97105
>
98106
<img
99107
alt="User uploaded content"
108+
src="about:blank"
100109
/>
101110
</button>
102111
<button
@@ -106,6 +115,7 @@ exports[`Gallery should render component with 5 images 1`] = `
106115
>
107116
<img
108117
alt="User uploaded content"
118+
src="about:blank"
109119
/>
110120
</button>
111121
<button
@@ -136,6 +146,7 @@ exports[`Gallery should render component with default props 1`] = `
136146
>
137147
<img
138148
alt="User uploaded content"
149+
src="about:blank"
139150
/>
140151
</button>
141152
<button
@@ -145,6 +156,7 @@ exports[`Gallery should render component with default props 1`] = `
145156
>
146157
<img
147158
alt="User uploaded content"
159+
src="about:blank"
148160
/>
149161
</button>
150162
</div>

src/components/MessageList/hooks/useMessageListElements.tsx

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -101,13 +101,7 @@ export const useMessageListElements = <
101101

102102
if (message.type === 'system') {
103103
return (
104-
<li
105-
key={
106-
(message.event as { created_at: string })?.created_at ||
107-
(message.created_at as string) ||
108-
''
109-
}
110-
>
104+
<li key={message.id || (message.created_at as string)}>
111105
<MessageSystem message={message} />
112106
</li>
113107
);

0 commit comments

Comments
 (0)