diff --git a/projects/stream-chat-angular/src/lib/attachment-list/attachment-list.component.html b/projects/stream-chat-angular/src/lib/attachment-list/attachment-list.component.html
index e656aa84..5ba935b2 100644
--- a/projects/stream-chat-angular/src/lib/attachment-list/attachment-list.component.html
+++ b/projects/stream-chat-angular/src/lib/attachment-list/attachment-list.component.html
@@ -26,6 +26,7 @@
>
+
@@ -106,6 +114,7 @@
"
>
+
+
{
let fixture: ComponentFixture
;
let attachmentUploads$: Subject;
let queryImagePreviews: () => HTMLElement[];
+ let queryImageFallbacks: () => HTMLElement[];
let queryLoadingIndicators: () => HTMLElement[];
let queryPreviewImages: () => HTMLImageElement[];
let queryPreviewFiles: () => HTMLElement[];
@@ -46,6 +47,12 @@ describe('AttachmentPreviewListComponent', () => {
'[data-testclass="attachment-file-preview"]'
)
);
+ queryImageFallbacks = () =>
+ Array.from(
+ nativeElement.querySelectorAll(
+ '[data-testclass="str-chat__image-fallback"]'
+ )
+ );
component.attachmentUploads$ = attachmentUploads$;
fixture.detectChanges();
});
@@ -188,6 +195,7 @@ describe('AttachmentPreviewListComponent', () => {
const previewImage = queryPreviewImages()[0];
expect(previewImage.src).toContain(previewUri);
+ expect(queryImageFallbacks().length).toBe(0);
const url = 'http://url/to/img';
attachmentUploads$.next([{ file, state: 'success', url, type: 'image' }]);
@@ -196,6 +204,22 @@ describe('AttachmentPreviewListComponent', () => {
expect(previewImage.src).toContain(url);
});
+ it(`should display image fallback if preview isn't working`, () => {
+ const file = { name: 'my_image.png', type: 'image/png' } as File;
+ const attachmentUpload = {
+ file,
+ state: 'success' as 'success',
+ url: 'http://url/to/img',
+ type: 'image' as 'image',
+ };
+ attachmentUploads$.next([attachmentUpload]);
+ component.imagePreviewErrors = [attachmentUpload];
+ fixture.detectChanges();
+
+ expect(queryPreviewImages().length).toBe(0);
+ expect(queryImageFallbacks().length).toBe(1);
+ });
+
it('should retry file upload', () => {
const upload = {
file: { name: 'contract.pdf', type: 'application/pdf' } as File,
diff --git a/projects/stream-chat-angular/src/lib/attachment-preview-list/attachment-preview-list.component.ts b/projects/stream-chat-angular/src/lib/attachment-preview-list/attachment-preview-list.component.ts
index bd1fa04f..121cbccc 100644
--- a/projects/stream-chat-angular/src/lib/attachment-preview-list/attachment-preview-list.component.ts
+++ b/projects/stream-chat-angular/src/lib/attachment-preview-list/attachment-preview-list.component.ts
@@ -1,7 +1,16 @@
-import { Component, EventEmitter, Input, Output } from '@angular/core';
-import { Observable } from 'rxjs';
+import {
+ Component,
+ EventEmitter,
+ Input,
+ OnChanges,
+ OnDestroy,
+ Output,
+ SimpleChanges,
+} from '@angular/core';
+import { Observable, Subscription } from 'rxjs';
import { ThemeService } from '../theme.service';
import { AttachmentUpload } from '../types';
+import { Attachment } from 'stream-chat';
/**
* The `AttachmentPreviewList` component displays a preview of the attachments uploaded to a message. Users can delete attachments using the preview component, or retry upload if it failed previously.
@@ -11,7 +20,7 @@ import { AttachmentUpload } from '../types';
templateUrl: './attachment-preview-list.component.html',
styles: [],
})
-export class AttachmentPreviewListComponent {
+export class AttachmentPreviewListComponent implements OnChanges, OnDestroy {
/**
* A stream that emits the current file uploads and their states
*/
@@ -25,10 +34,28 @@ export class AttachmentPreviewListComponent {
*/
@Output() readonly deleteAttachment = new EventEmitter();
themeVersion: '1' | '2';
+ imagePreviewErrors: Attachment[] = [];
+ private attachmentUploadsSubscription?: Subscription;
constructor(themeService: ThemeService) {
this.themeVersion = themeService.themeVersion;
}
+ ngOnChanges(changes: SimpleChanges): void {
+ if (changes.attachmentUploads$) {
+ this.attachmentUploadsSubscription?.unsubscribe();
+ this.attachmentUploadsSubscription = this.attachmentUploads$?.subscribe(
+ (attachments) => {
+ if (attachments.length === 0) {
+ this.imagePreviewErrors = [];
+ }
+ }
+ );
+ }
+ }
+
+ ngOnDestroy(): void {
+ this.attachmentUploadsSubscription?.unsubscribe();
+ }
attachmentUploadRetried(file: File) {
this.retryAttachmentUpload.emit(file);
diff --git a/projects/stream-chat-angular/src/lib/icon/icon.component.html b/projects/stream-chat-angular/src/lib/icon/icon.component.html
index 980c23cc..1bc7f3af 100644
--- a/projects/stream-chat-angular/src/lib/icon/icon.component.html
+++ b/projects/stream-chat-angular/src/lib/icon/icon.component.html
@@ -378,3 +378,14 @@
/>
+
diff --git a/projects/stream-chat-angular/src/lib/icon/icon.component.ts b/projects/stream-chat-angular/src/lib/icon/icon.component.ts
index 142b172a..757acdcb 100644
--- a/projects/stream-chat-angular/src/lib/icon/icon.component.ts
+++ b/projects/stream-chat-angular/src/lib/icon/icon.component.ts
@@ -22,7 +22,8 @@ export type Icon =
| 'attach'
| 'unspecified-filetype'
| 'download'
- | 'error';
+ | 'error'
+ | 'image-fallback';
/**
* The `Icon` component can be used to display different icons (i. e. message delivered icon).