Chat shows new messages
This commit is contained in:
47
src/app/services/chat-message-handler.ts
Normal file
47
src/app/services/chat-message-handler.ts
Normal 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);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user