Skip to content

Commit

Permalink
Merge pull request #499 from GetStream/empty-channel-placeholder
Browse files Browse the repository at this point in the history
Empty channel placeholder
  • Loading branch information
szuperaz authored Nov 9, 2023
2 parents 230c3d2 + 6b9a2ee commit f2aa7c1
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 3 deletions.
8 changes: 8 additions & 0 deletions projects/customizations-example/src/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -282,3 +282,11 @@
<ng-template #dateSeparator let-date="date" let-parsedDate="parsedDate">
{{ date }} - {{ parsedDate }}
</ng-template>

<ng-template #emptyMainMessageList>
<div class="empty-list"><div>No messages yet</div></div>
</ng-template>

<ng-template #emptyThreadMessageList>
<div class="empty-list"><div>No thread replies yet</div></div>
</ng-template>
7 changes: 7 additions & 0 deletions projects/customizations-example/src/app/app.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.empty-list {
display: flex;
width: 100%;
height: 100%;
align-items: center;
justify-content: center;
}
10 changes: 10 additions & 0 deletions projects/customizations-example/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ export class AppComponent implements AfterViewInit {
private customAttachmentUploadTemplate!: TemplateRef<CustomAttachmentUploadContext>;
@ViewChild('dateSeparator')
private dateSeparatorTemplate!: TemplateRef<DateSeparatorContext>;
@ViewChild('emptyMainMessageList')
private emptyMainMessageListTemplate!: TemplateRef<void>;
@ViewChild('emptyThreadMessageList')
private emptyThreadMessageListTemplate!: TemplateRef<void>;

constructor(
private chatService: ChatClientService,
Expand Down Expand Up @@ -170,6 +174,12 @@ export class AppComponent implements AfterViewInit {
this.customTemplatesService.dateSeparatorTemplate$.next(
this.dateSeparatorTemplate
);
this.customTemplatesService.emptyMainMessageListPlaceholder$.next(
this.emptyMainMessageListTemplate
);
this.customTemplatesService.emptyThreadMessageListPlaceholder$.next(
this.emptyThreadMessageListTemplate
);
}

inviteClicked(channel: Channel) {
Expand Down
5 changes: 5 additions & 0 deletions projects/customizations-example/src/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,8 @@ body {
.material-icons {
font-family: "Material Icons" !important;
}

.str-chat__thread
.str-chat__main-panel-inner.str-chat-angular__message-list-host--empty {
height: 100%;
}
12 changes: 12 additions & 0 deletions projects/stream-chat-angular/src/lib/custom-templates.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,18 @@ export class CustomTemplatesService {
newMessagesIndicatorTemplate$ = new BehaviorSubject<
TemplateRef<void> | undefined
>(undefined);
/**
* The template to show if the main message list is empty
*/
emptyMainMessageListPlaceholder$ = new BehaviorSubject<
TemplateRef<void> | undefined
>(undefined);
/**
* The template to show if the thread message list is empty
*/
emptyThreadMessageListPlaceholder$ = new BehaviorSubject<
TemplateRef<void> | undefined
>(undefined);

constructor() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
class="str-chat__list"
style="overscroll-behavior: none"
>
<ng-container *ngIf="mode === 'main' && isEmpty && emptyListTemplate">
<ng-container *ngTemplateOutlet="emptyListTemplate"></ng-container>
</ng-container>
<div class="str-chat__reverse-infinite-scroll str-chat__message-list-scroll">
<ul
class="str-chat__ul"
Expand All @@ -28,6 +31,9 @@
replies' | translate:replyCountParam)}}
</div>
</li>
<ng-container *ngIf="mode === 'thread' && isEmpty && emptyListTemplate">
<ng-container *ngTemplateOutlet="emptyListTemplate"></ng-container>
</ng-container>
<stream-loading-indicator
data-testid="top-loading-indicator"
*ngIf="
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
AfterViewChecked,
AfterViewInit,
ChangeDetectorRef,
Component,
ElementRef,
HostBinding,
Expand Down Expand Up @@ -87,10 +88,11 @@ export class MessageListComponent
messageTemplate: TemplateRef<MessageContext> | undefined;
customDateSeparatorTemplate: TemplateRef<DateSeparatorContext> | undefined;
customnewMessagesIndicatorTemplate: TemplateRef<void> | undefined;
emptyMainMessageListTemplate: TemplateRef<void> | null = null;
emptyThreadMessageListTemplate: TemplateRef<void> | null = null;
messages$!: Observable<StreamMessage[]>;
enabledMessageActions: string[] = [];
@HostBinding('class') private class =
'str-chat-angular__main-panel-inner str-chat-angular__message-list-host str-chat__main-panel-inner';
isEmpty = true;
unreadMessageCount = 0;
isUserScrolled: boolean | undefined;
groupStyles: GroupStyle[] = [];
Expand Down Expand Up @@ -125,12 +127,20 @@ export class MessageListComponent
private channelId?: string;
private parsedDates = new Map<Date, string>();

@HostBinding('class')
private get class() {
return `str-chat-angular__main-panel-inner str-chat-angular__message-list-host str-chat__main-panel-inner ${
this.isEmpty ? 'str-chat-angular__message-list-host--empty' : ''
}`;
}

constructor(
private channelService: ChannelService,
private chatClientService: ChatClientService,
private customTemplatesService: CustomTemplatesService,
private dateParser: DateParserService,
private ngZone: NgZone
private ngZone: NgZone,
private cdRef: ChangeDetectorRef
) {
this.subscriptions.push(
this.channelService.activeChannel$.subscribe((channel) => {
Expand Down Expand Up @@ -269,6 +279,28 @@ export class MessageListComponent
}
})
);
this.subscriptions.push(
this.customTemplatesService.emptyMainMessageListPlaceholder$.subscribe(
(template) => {
const isChanged = this.emptyMainMessageListTemplate !== template;
this.emptyMainMessageListTemplate = template || null;
if (isChanged) {
this.cdRef.detectChanges();
}
}
)
);
this.subscriptions.push(
this.customTemplatesService.emptyThreadMessageListPlaceholder$.subscribe(
(template) => {
const isChanged = this.emptyThreadMessageListTemplate !== template;
this.emptyThreadMessageListTemplate = template || null;
if (isChanged) {
this.cdRef.detectChanges();
}
}
)
);
}

ngAfterViewChecked() {
Expand Down Expand Up @@ -451,6 +483,12 @@ export class MessageListComponent
return { replyCount: this.parentMessage?.reply_count };
}

get emptyListTemplate() {
return this.mode === 'main'
? this.emptyMainMessageListTemplate
: this.emptyThreadMessageListTemplate;
}

private preserveScrollbarPosition() {
this.scrollContainer.nativeElement.scrollTop =
(this.prevScrollTop || 0) +
Expand Down Expand Up @@ -508,6 +546,10 @@ export class MessageListComponent
this.resetScrollState();
return;
}
if (this.isEmpty) {
// cdRef.detectChanges() isn't enough here, test will fail
setTimeout(() => (this.isEmpty = false), 0);
}
this.chatClientService.chatClient?.logger?.(
'info',
`Received one or more messages`,
Expand Down Expand Up @@ -574,6 +616,7 @@ export class MessageListComponent
}

private resetScrollState() {
this.isEmpty = true;
this.latestMessage = undefined;
this.hasNewMessages = true;
this.isUserScrolled = false;
Expand Down

0 comments on commit f2aa7c1

Please sign in to comment.