feat: Add chat seperator and restore last viewed chat on restart

This commit is contained in:
2026-04-02 00:47:44 +02:00
parent bbb6deb0a2
commit 5d7e045764
10 changed files with 412 additions and 18 deletions

View File

@@ -37,7 +37,17 @@
</div>
}
@for (message of messages(); track message.id) {
@for (message of messages(); track message.id; let index = $index) {
@if (dateSeparatorLabels().get(index); as separatorLabel) {
<div class="flex items-center gap-3 py-1">
<div class="h-px flex-1 bg-border"></div>
<span class="rounded-full border border-border bg-background/90 px-3 py-1 text-xs font-medium text-muted-foreground shadow-sm">
{{ separatorLabel }}
</span>
<div class="h-px flex-1 bg-border"></div>
</div>
}
<app-chat-message-item
[message]="message"
[repliedMessage]="findRepliedMessage(message.replyToId)"

View File

@@ -13,6 +13,7 @@ import {
signal
} from '@angular/core';
import { Attachment } from '../../../../../attachment';
import { getMessageTimestamp } from '../../../../domain/message.rules';
import { Message } from '../../../../../../shared-kernel';
import {
ChatMessageDeleteEvent,
@@ -45,6 +46,12 @@ declare global {
export class ChatMessageListComponent implements AfterViewChecked, OnDestroy {
@ViewChild('messagesContainer') messagesContainer?: ElementRef<HTMLDivElement>;
private readonly dateSeparatorFormatter = new Intl.DateTimeFormat('en-GB', {
day: 'numeric',
month: 'long',
year: 'numeric'
});
readonly allMessages = input.required<Message[]>();
readonly channelMessages = input.required<Message[]>();
readonly loading = input(false);
@@ -83,6 +90,23 @@ export class ChatMessageListComponent implements AfterViewChecked, OnDestroy {
() => this.channelMessages().length > this.displayLimit()
);
readonly dateSeparatorLabels = computed(() => {
const labels = new Map<number, string>();
let previousDayKey: string | null = null;
this.messages().forEach((message, index) => {
const timestamp = this.getMessageDateTimestamp(message);
const currentDayKey = this.getMessageDayKey(timestamp);
if (currentDayKey !== previousDayKey) {
labels.set(index, this.dateSeparatorFormatter.format(new Date(timestamp)));
previousDayKey = currentDayKey;
}
});
return labels;
});
private initialScrollObserver: MutationObserver | null = null;
private initialScrollTimer: ReturnType<typeof setTimeout> | null = null;
private boundOnImageLoad: (() => void) | null = null;
@@ -342,6 +366,16 @@ export class ChatMessageListComponent implements AfterViewChecked, OnDestroy {
}
}
private getMessageDateTimestamp(message: Message): number {
return message.timestamp || getMessageTimestamp(message);
}
private getMessageDayKey(timestamp: number): string {
const date = new Date(timestamp);
return `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`;
}
private scrollToBottomSmooth(): void {
const element = this.messagesContainer?.nativeElement;