Process events list client side
This commit is contained in:
101
matrixgw_frontend/src/utils/RoomEventsManager.ts
Normal file
101
matrixgw_frontend/src/utils/RoomEventsManager.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
import type {
|
||||
MatrixEvent,
|
||||
MatrixEventsList,
|
||||
} from "../api/matrix/MatrixApiEvent";
|
||||
import type { Room } from "../api/matrix/MatrixApiRoom";
|
||||
|
||||
export interface MessageReaction {
|
||||
event_id: string;
|
||||
account: string;
|
||||
key: string;
|
||||
}
|
||||
|
||||
export interface Message {
|
||||
event_id: string;
|
||||
sent: number;
|
||||
modified: boolean;
|
||||
reactions: MessageReaction[];
|
||||
content: string;
|
||||
image?: string;
|
||||
}
|
||||
|
||||
export class RoomEventsManager {
|
||||
readonly room: Room;
|
||||
private events: MatrixEvent[];
|
||||
messages: Message[];
|
||||
endToken?: string;
|
||||
|
||||
constructor(room: Room, initialMessages: MatrixEventsList) {
|
||||
this.room = room;
|
||||
this.events = [];
|
||||
this.messages = [];
|
||||
|
||||
this.processNewEvents(initialMessages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process events given by the API
|
||||
*/
|
||||
processNewEvents(evts: MatrixEventsList) {
|
||||
this.endToken = evts.end;
|
||||
this.events = [...this.events, ...evts.events];
|
||||
this.rebuildMessagesList();
|
||||
}
|
||||
|
||||
private rebuildMessagesList() {
|
||||
// Sorts events list to process oldest events first
|
||||
this.events.sort((a, b) => a.time - b.time);
|
||||
|
||||
// First, process redactions to skip redacted events
|
||||
let redacted = new Set(
|
||||
this.events
|
||||
.map((e) =>
|
||||
e.data.type === "m.room.redaction" ? e.data.redacts : undefined
|
||||
)
|
||||
.filter((e) => e !== undefined)
|
||||
);
|
||||
|
||||
for (const evt of this.events) {
|
||||
if (redacted.has(evt.id)) continue;
|
||||
|
||||
const data = evt.data;
|
||||
|
||||
// Message
|
||||
if (data.type === "m.room.message") {
|
||||
// Check if this message replaces another one
|
||||
if (data.content["m.relates_to"]) {
|
||||
const message = this.messages.find(
|
||||
(m) => m.event_id === data.content["m.relates_to"]?.event_id
|
||||
);
|
||||
if (!message) continue;
|
||||
message.modified = true;
|
||||
message.content = data.content.body;
|
||||
continue;
|
||||
}
|
||||
|
||||
this.messages.push({
|
||||
event_id: evt.id,
|
||||
modified: false,
|
||||
reactions: [],
|
||||
sent: evt.time,
|
||||
image: data.content.file?.url,
|
||||
content: data.content.body,
|
||||
});
|
||||
}
|
||||
|
||||
// Reaction
|
||||
if (data.type === "m.reaction") {
|
||||
const message = this.messages.find(
|
||||
(m) => m.event_id === data.content["m.relates_to"].event_id
|
||||
);
|
||||
|
||||
if (!message) continue;
|
||||
message.reactions.push({
|
||||
account: evt.sender,
|
||||
event_id: evt.id,
|
||||
key: data.content["m.relates_to"].key,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user