Skip to content

Commit 7ed2558

Browse files
committed
feat: Add custom attachment requests #255
1 parent 8db8285 commit 7ed2558

File tree

2 files changed

+135
-3
lines changed

2 files changed

+135
-3
lines changed

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

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1358,4 +1358,106 @@ describe('ChannelService', () => {
13581358

13591359
expect(spy).toHaveBeenCalledWith({ channel1: newMessage.created_at });
13601360
});
1361+
1362+
it('should call custom #customFileUploadRequest and #customImageUploadRequest if provided', async () => {
1363+
await init();
1364+
let channel!: Channel<DefaultStreamChatGenerics>;
1365+
service.activeChannel$.pipe(first()).subscribe((c) => (channel = c!));
1366+
const customImageUploadRequest = jasmine
1367+
.createSpy()
1368+
.and.callFake((file: File) => {
1369+
switch (file.name) {
1370+
case 'file_error.jpg':
1371+
return Promise.reject(new Error());
1372+
default:
1373+
return Promise.resolve({ file: 'url/to/image' });
1374+
}
1375+
});
1376+
const customFileUploadRequest = jasmine
1377+
.createSpy()
1378+
.and.callFake((file: File) => {
1379+
switch (file.name) {
1380+
case 'file_error.pdf':
1381+
return Promise.reject(new Error());
1382+
default:
1383+
return Promise.resolve({ file: 'url/to/pdf' });
1384+
}
1385+
});
1386+
service.customImageUploadRequest = customImageUploadRequest;
1387+
service.customFileUploadRequest = customFileUploadRequest;
1388+
spyOn(channel, 'sendImage');
1389+
spyOn(channel, 'sendFile');
1390+
const file1 = { name: 'food.png' } as File;
1391+
const file2 = { name: 'file_error.jpg' } as File;
1392+
const file3 = { name: 'menu.pdf' } as File;
1393+
const file4 = { name: 'file_error.pdf' } as File;
1394+
const attachments = [
1395+
{ file: file1, type: 'image', state: 'uploading' },
1396+
{ file: file2, type: 'image', state: 'uploading' },
1397+
{ file: file3, type: 'file', state: 'uploading' },
1398+
{ file: file4, type: 'file', state: 'uploading' },
1399+
] as AttachmentUpload[];
1400+
const result = await service.uploadAttachments(attachments);
1401+
const expectedResult = [
1402+
{
1403+
file: file1,
1404+
state: 'success',
1405+
url: 'url/to/image',
1406+
type: 'image',
1407+
},
1408+
{ file: file2, state: 'error', type: 'image' },
1409+
{
1410+
file: file3,
1411+
state: 'success',
1412+
url: 'url/to/pdf',
1413+
type: 'file',
1414+
},
1415+
{ file: file4, state: 'error', type: 'file' },
1416+
];
1417+
1418+
expect(channel.sendImage).not.toHaveBeenCalled();
1419+
expect(channel.sendFile).not.toHaveBeenCalled();
1420+
1421+
expectedResult.forEach((r, i) => {
1422+
expect(r).toEqual(result[i]);
1423+
});
1424+
});
1425+
1426+
it('should call custom #customImageDeleteRequest if provided', async () => {
1427+
await init();
1428+
let channel!: Channel<DefaultStreamChatGenerics>;
1429+
service.activeChannel$.pipe(first()).subscribe((c) => (channel = c!));
1430+
const customImageDeleteRequest = jasmine.createSpy();
1431+
service.customImageDeleteRequest = customImageDeleteRequest;
1432+
spyOn(channel, 'deleteImage');
1433+
const url = 'url/to/image';
1434+
await service.deleteAttachment({
1435+
url,
1436+
type: 'image',
1437+
state: 'success',
1438+
file: {} as any as File,
1439+
});
1440+
1441+
expect(customImageDeleteRequest).toHaveBeenCalledWith(url, channel);
1442+
expect(channel.deleteImage).not.toHaveBeenCalled();
1443+
});
1444+
1445+
it('should call custom #customFileDeleteRequest if provided', async () => {
1446+
await init();
1447+
let channel!: Channel<DefaultStreamChatGenerics>;
1448+
service.activeChannel$.pipe(first()).subscribe((c) => (channel = c!));
1449+
const customFileDeleteRequest = jasmine.createSpy();
1450+
service.customFileDeleteRequest = customFileDeleteRequest;
1451+
spyOn(channel, 'deleteFile');
1452+
const url = 'url/to/file';
1453+
await service.deleteAttachment({
1454+
url,
1455+
type: 'file',
1456+
state: 'success',
1457+
file: {} as any as File,
1458+
});
1459+
1460+
expect(customFileDeleteRequest).toHaveBeenCalledWith(url, channel);
1461+
expect(channel.deleteFile).not.toHaveBeenCalled();
1462+
});
13611463
});

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

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ import {
2121
} from 'stream-chat';
2222
import { ChatClientService, Notification } from './chat-client.service';
2323
import { createMessagePreview } from './message-preview';
24-
import { MessageReactionType } from './message-reactions/message-reactions.component';
2524
import { getReadBy } from './read-by';
2625
import { AttachmentUpload, StreamMessage } from './types';
26+
import { MessageReactionType } from './message-reactions/message-reactions.component';
2727

2828
/**
2929
* The `ChannelService` provides data and interaction for the channel list and message list. TEST
@@ -189,6 +189,28 @@ export class ChannelService {
189189
threadListSetter: (messages: StreamMessage[]) => void,
190190
parentMessageSetter: (message: StreamMessage | undefined) => void
191191
) => void;
192+
/**
193+
* You can override the default file upload request - you can use this to upload files to your own CDN
194+
*/
195+
customFileUploadRequest?: (
196+
file: File,
197+
channel: Channel
198+
) => Promise<{ file: string }>;
199+
/**
200+
* You can override the default image upload request - you can use this to upload images to your own CDN
201+
*/
202+
customImageUploadRequest?: (
203+
file: File,
204+
channel: Channel
205+
) => Promise<{ file: string }>;
206+
/**
207+
* You can override the default file delete request - override this if you use your own CDN
208+
*/
209+
customFileDeleteRequest?: (url: string, channel: Channel) => Promise<void>;
210+
/**
211+
* You can override the default image delete request - override this if you use your own CDN
212+
*/
213+
customImageDeleteRequest?: (url: string, channel: Channel) => Promise<void>;
192214
private channelsSubject = new BehaviorSubject<Channel[] | undefined>(
193215
undefined
194216
);
@@ -549,7 +571,11 @@ export class ChannelService {
549571
const uploadResults = await Promise.allSettled(
550572
uploads.map((upload) =>
551573
upload.type === 'image'
552-
? channel.sendImage(upload.file)
574+
? this.customImageUploadRequest
575+
? this.customImageUploadRequest(upload.file, channel)
576+
: channel.sendImage(upload.file)
577+
: this.customFileUploadRequest
578+
? this.customFileUploadRequest(upload.file, channel)
553579
: channel.sendFile(upload.file)
554580
)
555581
);
@@ -578,7 +604,11 @@ export class ChannelService {
578604
async deleteAttachment(attachmentUpload: AttachmentUpload) {
579605
const channel = this.activeChannelSubject.getValue()!;
580606
await (attachmentUpload.type === 'image'
581-
? channel.deleteImage(attachmentUpload.url!)
607+
? this.customImageDeleteRequest
608+
? this.customImageDeleteRequest(attachmentUpload.url!, channel)
609+
: channel.deleteImage(attachmentUpload.url!)
610+
: this.customFileDeleteRequest
611+
? this.customFileDeleteRequest(attachmentUpload.url!, channel)
582612
: channel.deleteFile(attachmentUpload.url!));
583613
}
584614

0 commit comments

Comments
 (0)