Chat shows new messages

This commit is contained in:
2021-04-02 13:40:26 +02:00
parent 45e3ada041
commit ac6cd02a7c
3 changed files with 90 additions and 46 deletions

View File

@@ -0,0 +1,47 @@
import { Observable, Subject } from 'rxjs';
import { MatrixClient } from 'matrix-js-sdk/src/client';
import { MatrixEvent } from 'matrix-js-sdk/src/models/event';
import { EventTimeline } from 'matrix-js-sdk/src/models/event-timeline';
import { Room } from 'matrix-js-sdk/src/models/room';
export class ChatMessageHandler {
constructor(
private matrixClientPromise: Promise<MatrixClient>,
) { }
getRoomMessages = (roomId: string) => {
const subject = new Subject<MatrixEvent>();
this.publishRoomOldMessages(roomId, subject);
this.publishRoomNewMessages(roomId, subject);
return subject;
}
private publishRoomOldMessages(roomId: string, subject: Subject<MatrixEvent>): void {
this.matrixClientPromise.then(client => {
const room = client.getRoom(roomId) as Room;
room?.timeline
.filter((t: MatrixEvent) => (t.getType() === 'm.room.message'))
.forEach(message => subject.next(message));
});
}
private publishRoomNewMessages(roomId: string, subject: Subject<MatrixEvent>): void {
this.matrixClientPromise.then(client => {
client.on('Room.timeline', (event: EventTimeline, room: Room, toStartOfTimeline: boolean) => {
if (room.roomId !== roomId) {
return; // only listen to specified room
}
if (toStartOfTimeline) {
return; // don't print paginated results
}
if (event.getType() !== 'm.room.message') {
return; // only print messages
}
subject.next(event);
});
});
}
}

View File

@@ -3,17 +3,23 @@ import { Injectable } from '@angular/core';
import * as olm from 'olm';
global.Olm = olm;
import * as matrix from 'matrix-js-sdk';
import { MatrixClient } from 'matrix-js-sdk/src/client';
import { RoomMember } from 'matrix-js-sdk/src/models/room';
import { Room } from 'matrix-js-sdk/src/models/room';
import { EventTimeline } from 'matrix-js-sdk/src/models/event-timeline';
import { MatrixLoginDto } from '../entities/matrix-login-dto';
import { MatrixEvent } from 'matrix-js-sdk/src/models/event';
import { Observable, Subject } from 'rxjs';
import { ChatMessageHandler } from './chat-message-handler';
@Injectable({
providedIn: 'root'
})
export class ChatService {
private client: any;
private matrixClient: MatrixClient;
private chatMessageHandler: ChatMessageHandler;
getRoomMessages: (roomId: string) => (Observable<MatrixEvent>);
constructor(
private http: HttpClient
@@ -23,7 +29,15 @@ export class ChatService {
window.location.href = 'http://synapse:8008/_matrix/client/r0/login/sso/redirect?redirectUrl=http://localhost:4200/';
}
async login(loginToken: string): Promise<void> {
login(loginToken: string): Promise<MatrixClient> {
const matrixClientPromise = this.loginWithToken(loginToken);
this.chatMessageHandler = new ChatMessageHandler(matrixClientPromise);
this.getRoomMessages = this.chatMessageHandler.getRoomMessages;
return matrixClientPromise;
}
private async loginWithToken(loginToken: string): Promise<MatrixClient> {
const matrixLogin = await this.http.post<MatrixLoginDto>(
'http://synapse:8008/_matrix/client/r0/login',
{
@@ -33,50 +47,28 @@ export class ChatService {
}
).toPromise();
console.log('LOGGED TO CHAT');
console.log(matrixLogin);
this.client = matrix.createClient({
console.log({ matrixLogin });
this.matrixClient = matrix.createClient({
baseUrl: 'http://localhost:8008',
accessToken: matrixLogin.access_token,
userId: matrixLogin.user_id
});
await this.client.startClient({ initialSyncLimit: 100 });
await this.matrixClient.startClient({ initialSyncLimit: 100 });
this.client.once('sync', (state: string, prevState: string, _: any) => {
this.matrixClient.once('sync', (state: string, prevState: string, _: any) => {
if (state === 'PREPARED') {
console.log('CHAT SYNC FINISHED');
} else {
console.log(state);
}
});
}
getRoomMessages(roomId: string): MatrixEvent[] {
console.log('roomId=' + roomId);
const room: Room = this.client?.getRoom(roomId) as Room;
console.log({room});
return room?.timeline
.filter((t: MatrixEvent) => (t.getType() === 'm.room.message'));
return this.matrixClient;
}
getRoomMembers(roomId: string): RoomMember[] {
const room: Room = this.client?.getRoom(roomId) as Room;
const room: Room = this.matrixClient?.getRoom(roomId) as Room;
return room?.getJoinedMembers();
}
listemRoomMessages(roomId: string, handle: (event: EventTimeline) => void): void {
this.client?.on('Room.timeline', (event: EventTimeline, room: Room, toStartOfTimeline: boolean) => {
if (room.roomId !== roomId) {
return; // only listen to specified room
}
if (toStartOfTimeline) {
return; // don't print paginated results
}
if (event.getType() !== 'm.room.message') {
return; // only print messages
}
handle(event);
});
}
}

View File

@@ -1,10 +1,9 @@
import { Component, Input, OnInit, AfterViewInit, ElementRef, ViewChildren } from '@angular/core';
import { Component, Input, OnInit, AfterViewInit, ElementRef, ViewChildren, ChangeDetectorRef } from '@angular/core';
import { ChatService } from 'src/app/services/chat.service';
import { RoomMember } from 'matrix-js-sdk/src/models/room';
import { Room } from 'matrix-js-sdk/src/models/room';
import { MatrixEvent } from 'matrix-js-sdk/src/models/event';
import { QueryList } from '@angular/core';
import { Observable } from 'rxjs';
@Component({
selector: 'app-chat',
@@ -14,27 +13,33 @@ import { QueryList } from '@angular/core';
export class ChatComponent implements OnInit, AfterViewInit {
@Input() roomId: string;
@ViewChildren('messageItem', { read: ElementRef }) messageItems: QueryList<ElementRef>;
messages: MatrixEvent[];
messages: MatrixEvent[] = new Array();
constructor(private chatService: ChatService) { }
constructor(
private chatService: ChatService,
private changeDetection: ChangeDetectorRef
) { }
ngOnInit(): void {
this.messages = this.chatService.getRoomMessages(this.roomId);
if (this.chatService.getRoomMessages !== undefined) {
const messages$ = this.chatService.getRoomMessages(this.roomId);
this.chatService.listemRoomMessages(this.roomId, (event: any) => {
console.log(
// the room name will update with m.room.name events automatically
'%s: %s', event.getSender(), event.getContent().body
);
});
messages$.subscribe({
next: (event: MatrixEvent) => {
this.messages.push(event);
this.changeDetection.detectChanges();
}
});
}
}
ngAfterViewInit(): void {
// Always scroll to last chat message.
this.messageItems?.last.nativeElement?.scrollIntoView(false);
this.messageItems.changes.subscribe((c) => {
console.log({ c });
this.messageItems?.last.nativeElement?.scrollIntoView(false);
this.messageItems.last?.nativeElement?.scrollIntoView(false);
this.messageItems.changes.subscribe({
next: (c) => {
this.messageItems.last?.nativeElement?.scrollIntoView(false);
}
});
}