You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-08-09 10:22:46 +03:00
Merge pull request #2912 from matrix-org/kegan/ss-receipts
sliding sync: add receipts extension
This commit is contained in:
@@ -928,4 +928,90 @@ describe("SlidingSyncSdk", () => {
|
||||
expect(room.getMember(selfUserId)?.typing).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("ExtensionReceipts", () => {
|
||||
let ext: Extension;
|
||||
|
||||
const generateReceiptResponse = (
|
||||
userId: string, roomId: string, eventId: string, recType: string, ts: number,
|
||||
) => {
|
||||
return {
|
||||
rooms: {
|
||||
[roomId]: {
|
||||
type: EventType.Receipt,
|
||||
content: {
|
||||
[eventId]: {
|
||||
[recType]: {
|
||||
[userId]: {
|
||||
ts: ts,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
beforeAll(async () => {
|
||||
await setupClient();
|
||||
const hasSynced = sdk!.sync();
|
||||
await httpBackend!.flushAllExpected();
|
||||
await hasSynced;
|
||||
ext = findExtension("receipts");
|
||||
});
|
||||
|
||||
it("gets enabled on the initial request only", () => {
|
||||
expect(ext.onRequest(true)).toEqual({
|
||||
enabled: true,
|
||||
});
|
||||
expect(ext.onRequest(false)).toEqual(undefined);
|
||||
});
|
||||
|
||||
it("processes receipts", async () => {
|
||||
const roomId = "!room:id";
|
||||
const alice = "@alice:alice";
|
||||
const lastEvent = mkOwnEvent(EventType.RoomMessage, { body: "hello" });
|
||||
mockSlidingSync!.emit(SlidingSyncEvent.RoomData, roomId, {
|
||||
name: "Room with receipts",
|
||||
required_state: [],
|
||||
timeline: [
|
||||
mkOwnStateEvent(EventType.RoomCreate, { creator: selfUserId }, ""),
|
||||
mkOwnStateEvent(EventType.RoomMember, { membership: "join" }, selfUserId),
|
||||
mkOwnStateEvent(EventType.RoomPowerLevels, { users: { [selfUserId]: 100 } }, ""),
|
||||
{
|
||||
type: EventType.RoomMember,
|
||||
state_key: alice,
|
||||
content: { membership: "join" },
|
||||
sender: alice,
|
||||
origin_server_ts: Date.now(),
|
||||
event_id: "$alice",
|
||||
},
|
||||
lastEvent,
|
||||
],
|
||||
initial: true,
|
||||
});
|
||||
const room = client!.getRoom(roomId)!;
|
||||
expect(room).toBeDefined();
|
||||
expect(room.getReadReceiptForUserId(alice, true)).toBeNull();
|
||||
ext.onResponse(
|
||||
generateReceiptResponse(alice, roomId, lastEvent.event_id, "m.read", 1234567),
|
||||
);
|
||||
const receipt = room.getReadReceiptForUserId(alice);
|
||||
expect(receipt).toBeDefined();
|
||||
expect(receipt?.eventId).toEqual(lastEvent.event_id);
|
||||
expect(receipt?.data.ts).toEqual(1234567);
|
||||
expect(receipt?.data.thread_id).toBeFalsy();
|
||||
});
|
||||
|
||||
it("gracefully handles missing rooms when receiving receipts", async () => {
|
||||
const roomId = "!room:id";
|
||||
const alice = "@alice:alice";
|
||||
const eventId = "$something";
|
||||
ext.onResponse(
|
||||
generateReceiptResponse(alice, roomId, eventId, "m.read", 1234567),
|
||||
);
|
||||
// we expect it not to crash
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -246,29 +246,55 @@ class ExtensionTyping implements Extension {
|
||||
|
||||
public onRequest(isInitial: boolean): object | undefined {
|
||||
if (!isInitial) {
|
||||
return undefined;
|
||||
return undefined; // don't send a JSON object for subsequent requests, we don't need to.
|
||||
}
|
||||
return {
|
||||
enabled: true,
|
||||
};
|
||||
}
|
||||
|
||||
public onResponse(data: {rooms: Record<string, Event[]>}): void {
|
||||
public onResponse(data: {rooms: Record<string, IMinimalEvent>}): void {
|
||||
if (!data || !data.rooms) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const roomId in data.rooms) {
|
||||
const ephemeralEvents = mapEvents(this.client, roomId, [data.rooms[roomId]]);
|
||||
const room = this.client.getRoom(roomId);
|
||||
if (!room) {
|
||||
logger.warn("got typing events for room but room doesn't exist on client:", roomId);
|
||||
continue;
|
||||
}
|
||||
room.addEphemeralEvents(ephemeralEvents);
|
||||
ephemeralEvents.forEach((e) => {
|
||||
this.client.emit(ClientEvent.Event, e);
|
||||
});
|
||||
processEphemeralEvents(
|
||||
this.client, roomId, [data.rooms[roomId]],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ExtensionReceipts implements Extension {
|
||||
public constructor(private readonly client: MatrixClient) {}
|
||||
|
||||
public name(): string {
|
||||
return "receipts";
|
||||
}
|
||||
|
||||
public when(): ExtensionState {
|
||||
return ExtensionState.PostProcess;
|
||||
}
|
||||
|
||||
public onRequest(isInitial: boolean): object | undefined {
|
||||
if (isInitial) {
|
||||
return {
|
||||
enabled: true,
|
||||
};
|
||||
}
|
||||
return undefined; // don't send a JSON object for subsequent requests, we don't need to.
|
||||
}
|
||||
|
||||
public onResponse(data: {rooms: Record<string, IMinimalEvent>}): void {
|
||||
if (!data || !data.rooms) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const roomId in data.rooms) {
|
||||
processEphemeralEvents(
|
||||
this.client, roomId, [data.rooms[roomId]],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -314,6 +340,7 @@ export class SlidingSyncSdk {
|
||||
new ExtensionToDevice(this.client),
|
||||
new ExtensionAccountData(this.client),
|
||||
new ExtensionTyping(this.client),
|
||||
new ExtensionReceipts(this.client),
|
||||
];
|
||||
if (this.opts.crypto) {
|
||||
extensions.push(
|
||||
@@ -929,3 +956,16 @@ function mapEvents(client: MatrixClient, roomId: string | undefined, events: obj
|
||||
return mapper(e);
|
||||
});
|
||||
}
|
||||
|
||||
function processEphemeralEvents(client: MatrixClient, roomId: string, ephEvents: IMinimalEvent[]): void {
|
||||
const ephemeralEvents = mapEvents(client, roomId, ephEvents);
|
||||
const room = client.getRoom(roomId);
|
||||
if (!room) {
|
||||
logger.warn("got ephemeral events for room but room doesn't exist on client:", roomId);
|
||||
return;
|
||||
}
|
||||
room.addEphemeralEvents(ephemeralEvents);
|
||||
ephemeralEvents.forEach((e) => {
|
||||
client.emit(ClientEvent.Event, e);
|
||||
});
|
||||
}
|
||||
|
Reference in New Issue
Block a user