Skip to content

Commit 7057d8d

Browse files
authored
Merge pull request #512 from GetStream/better-errors-for-attachment-upload
Better errors for attachment upload
2 parents e92241e + 0a22c67 commit 7057d8d

File tree

8 files changed

+141
-24
lines changed

8 files changed

+141
-24
lines changed

package-lock.json

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@
117117
"@ngx-translate/core": "^13.0.0",
118118
"@ngx-translate/http-loader": "^6.0.0",
119119
"@popperjs/core": "^2.11.5",
120-
"@stream-io/stream-chat-css": "3.12.0",
120+
"@stream-io/stream-chat-css": "4.0.1",
121121
"@stream-io/transliterate": "^1.5.2",
122122
"angular-mentions": "^1.4.0",
123123
"dayjs": "^1.10.7",

projects/stream-chat-angular/src/assets/i18n/en.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,11 @@ export const en = {
2323
'Error pinning message': 'Error pinning message',
2424
'Error removing message pin': 'Error removing message pin',
2525
'Error unmuting a user ...': 'Error unmuting a user ...',
26-
'Error uploading file': 'Error uploading file',
27-
'Error uploading image': 'Error uploading image',
26+
'Error uploading file': 'Error uploading file "{{ name }}"',
27+
'Error uploading file, maximum file size exceeded':
28+
'Error uploading "{{ name }}", maximum file size {{ limit }} exceeded',
29+
'Error uploading file, extension not supported':
30+
'Error uploading "{{ name }}", extension {{ ext }} not supported',
2831
'Error deleting attachment': 'Error deleting attachment',
2932
'Error · Unsent': "Message couldn't be sent",
3033
'Error: {{ errorMessage }}': 'Error: {{ errorMessage }}',

projects/stream-chat-angular/src/lib/attachment.service.spec.ts

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -145,19 +145,37 @@ describe('AttachmentService', () => {
145145
const image = { name: 'my_image.png', type: 'image/png' } as File;
146146
const file = { name: 'user_guide.pdf', type: 'application/pdf' } as File;
147147
uploadAttachmentsSpy.and.resolveTo([
148-
{ file: image, state: 'error', type: 'image' },
149-
{ file, state: 'error', type: 'file' },
148+
{
149+
file: image,
150+
state: 'error',
151+
type: 'image',
152+
errorReason: 'file-extension',
153+
errorExtraInfo: [{ param: '.jpg' }],
154+
},
155+
{
156+
file,
157+
state: 'error',
158+
type: 'file',
159+
errorReason: 'file-size',
160+
errorExtraInfo: [{ param: '50MB' }],
161+
},
150162
]);
151163
const notificationService = TestBed.inject(NotificationService);
152164
spyOn(notificationService, 'addTemporaryNotification');
153165
await service.filesSelected([image, file] as any as FileList);
154166

155167
expect(notificationService.addTemporaryNotification).toHaveBeenCalledWith(
156-
'streamChat.Error uploading image'
168+
'streamChat.Error uploading file, extension not supported',
169+
'error',
170+
undefined,
171+
{ name: image.name, ext: '.jpg' }
157172
);
158173

159174
expect(notificationService.addTemporaryNotification).toHaveBeenCalledWith(
160-
'streamChat.Error uploading file'
175+
'streamChat.Error uploading file, maximum file size exceeded',
176+
'error',
177+
undefined,
178+
{ name: file.name, limit: '50MB' }
161179
);
162180
});
163181

@@ -181,6 +199,8 @@ describe('AttachmentService', () => {
181199
url: 'image/url',
182200
type: 'image',
183201
thumb_url: undefined,
202+
errorReason: undefined,
203+
errorExtraInfo: undefined,
184204
},
185205
]);
186206
});

projects/stream-chat-angular/src/lib/attachment.service.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -258,10 +258,30 @@ export class AttachmentService<
258258
upload.url = r.url;
259259
upload.thumb_url = r.thumb_url;
260260
if (upload.state === 'error') {
261+
upload.errorReason = r.errorReason;
262+
upload.errorExtraInfo = r.errorExtraInfo;
263+
let errorKey;
264+
const translateParams: { name: string; ext?: string; limit?: string } =
265+
{ name: upload.file.name };
266+
switch (upload.errorReason) {
267+
case 'file-extension':
268+
errorKey =
269+
'streamChat.Error uploading file, extension not supported';
270+
translateParams.ext = upload.errorExtraInfo?.[0]?.param;
271+
break;
272+
case 'file-size':
273+
errorKey =
274+
'streamChat.Error uploading file, maximum file size exceeded';
275+
translateParams.limit = upload.errorExtraInfo?.[0]?.param;
276+
break;
277+
default:
278+
errorKey = 'streamChat.Error uploading file';
279+
}
261280
this.notificationService.addTemporaryNotification(
262-
upload.type === 'image'
263-
? 'streamChat.Error uploading image'
264-
: 'streamChat.Error uploading file'
281+
errorKey,
282+
'error',
283+
undefined,
284+
translateParams
265285
);
266286
}
267287
});

projects/stream-chat-angular/src/lib/channel.service.spec.ts

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1551,7 +1551,15 @@ describe('ChannelService', () => {
15511551
spyOn(channel, 'sendImage').and.callFake((file: File) => {
15521552
switch (file.name) {
15531553
case 'file_error.jpg':
1554-
return Promise.reject(new Error());
1554+
return Promise.reject({
1555+
response: {
1556+
data: {
1557+
code: 4,
1558+
message:
1559+
'UploadImage failed with error: "File extension .jpg is not supported"',
1560+
},
1561+
},
1562+
});
15551563
default:
15561564
return Promise.resolve({
15571565
file: 'http://url/to/image',
@@ -1563,7 +1571,15 @@ describe('ChannelService', () => {
15631571
(file: File, _: string, type: string) => {
15641572
switch (file.name) {
15651573
case 'file_error.pdf':
1566-
return Promise.reject(new Error());
1574+
return Promise.reject({
1575+
response: {
1576+
data: {
1577+
code: 22,
1578+
message:
1579+
'UploadFile failed with error: "max upload size of 50MB exceeded"',
1580+
},
1581+
},
1582+
});
15671583
default:
15681584
return Promise.resolve({
15691585
file: 'http://url/to/file',
@@ -1597,15 +1613,27 @@ describe('ChannelService', () => {
15971613
type: 'image',
15981614
thumb_url: undefined,
15991615
},
1600-
{ file: file2, state: 'error', type: 'image' },
1616+
{
1617+
file: file2,
1618+
state: 'error',
1619+
type: 'image',
1620+
errorReason: 'file-extension',
1621+
errorExtraInfo: [{ param: '.jpg' }],
1622+
},
16011623
{
16021624
file: file3,
16031625
state: 'success',
16041626
url: 'http://url/to/file',
16051627
type: 'file',
16061628
thumb_url: undefined,
16071629
},
1608-
{ file: file4, state: 'error', type: 'file' },
1630+
{
1631+
file: file4,
1632+
state: 'error',
1633+
type: 'file',
1634+
errorReason: 'file-size',
1635+
errorExtraInfo: [{ param: '50MB' }],
1636+
},
16091637
{
16101638
file: file5,
16111639
state: 'success',
@@ -1907,15 +1935,27 @@ describe('ChannelService', () => {
19071935
type: 'image',
19081936
thumb_url: undefined,
19091937
},
1910-
{ file: file2, state: 'error', type: 'image' },
1938+
{
1939+
file: file2,
1940+
state: 'error',
1941+
type: 'image',
1942+
errorReason: 'unknown',
1943+
errorExtraInfo: undefined,
1944+
},
19111945
{
19121946
file: file3,
19131947
state: 'success',
19141948
url: 'http://url/to/pdf',
19151949
type: 'file',
19161950
thumb_url: undefined,
19171951
},
1918-
{ file: file4, state: 'error', type: 'file' },
1952+
{
1953+
file: file4,
1954+
state: 'error',
1955+
type: 'file',
1956+
errorReason: 'unknown',
1957+
errorExtraInfo: undefined,
1958+
},
19191959
];
19201960

19211961
expect(channel.sendImage).not.toHaveBeenCalled();

projects/stream-chat-angular/src/lib/channel.service.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import { NotificationService } from './notification.service';
3030
import { getReadBy } from './read-by';
3131
import {
3232
AttachmentUpload,
33+
AttachmentUploadErrorReason,
3334
ChannelQueryState,
3435
DefaultStreamChatGenerics,
3536
MessageInput,
@@ -867,7 +868,33 @@ export class ChannelService<
867868
thumb_url: (uploadResult.value as any).thumb_url,
868869
});
869870
} else {
870-
result.push({ file, type, state: 'error' });
871+
let reason: AttachmentUploadErrorReason = 'unknown';
872+
let extraData: { param: string } | undefined;
873+
/* eslint-disable-next-line @typescript-eslint/no-unsafe-assignment */
874+
const message: string | undefined =
875+
/* eslint-disable-next-line @typescript-eslint/no-unsafe-member-access */
876+
uploadResult.reason.response?.data?.message;
877+
/* eslint-disable-next-line @typescript-eslint/no-unsafe-assignment */
878+
const code: number | undefined =
879+
/* eslint-disable-next-line @typescript-eslint/no-unsafe-member-access */
880+
uploadResult.reason.response?.data?.code;
881+
if (code === 22) {
882+
reason = 'file-size';
883+
extraData = { param: /\d+MB/.exec(message || '')?.[0] || '100MB' };
884+
} else if (
885+
code === 4 &&
886+
message?.toLowerCase()?.includes('file extension')
887+
) {
888+
reason = 'file-extension';
889+
extraData = { param: /\.\w+/.exec(message)?.[0] || '' };
890+
}
891+
result.push({
892+
file,
893+
type,
894+
state: 'error',
895+
errorReason: reason,
896+
errorExtraInfo: extraData ? [extraData] : undefined,
897+
});
871898
}
872899
});
873900

projects/stream-chat-angular/src/lib/types.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,18 @@ export type StreamMessage<
7979
T extends DefaultStreamChatGenerics = DefaultStreamChatGenerics
8080
> = FormatMessageResponse<T>;
8181

82+
export type AttachmentUploadErrorReason =
83+
| 'file-size'
84+
| 'file-extension'
85+
| 'unknown';
86+
8287
export type AttachmentUpload<
8388
T extends DefaultStreamChatGenerics = DefaultStreamChatGenerics
8489
> = {
8590
file: File;
8691
state: 'error' | 'success' | 'uploading';
92+
errorReason?: AttachmentUploadErrorReason;
93+
errorExtraInfo?: { param: string }[];
8794
url?: string;
8895
type: 'image' | 'file' | 'video';
8996
previewUri?: string | ArrayBuffer;

0 commit comments

Comments
 (0)