Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 25 additions & 13 deletions spec/unit/read-receipt.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import MockHttpBackend from 'matrix-mock-request';

import { ReceiptType } from '../../src/@types/read_receipts';
import { MatrixClient } from "../../src/client";
import { Feature, ServerSupport } from '../../src/feature';
import { EventType } from '../../src/matrix';
import { MAIN_ROOM_TIMELINE } from '../../src/models/read-receipt';
import { encodeUri } from '../../src/utils';
Expand Down Expand Up @@ -69,15 +70,8 @@ const roomEvent = utils.mkEvent({
},
});

function mockServerSideSupport(client, hasServerSideSupport) {
const doesServerSupportUnstableFeature = client.doesServerSupportUnstableFeature;
client.doesServerSupportUnstableFeature = (unstableFeature) => {
if (unstableFeature === "org.matrix.msc3771") {
return Promise.resolve(hasServerSideSupport);
} else {
return doesServerSupportUnstableFeature(unstableFeature);
}
};
function mockServerSideSupport(client, serverSideSupport: ServerSupport) {
client.canSupport.set(Feature.ThreadUnreadNotifications, serverSideSupport);
}

describe("Read receipt", () => {
Expand All @@ -103,13 +97,31 @@ describe("Read receipt", () => {
expect(request.data.thread_id).toEqual(THREAD_ID);
}).respond(200, {});

mockServerSideSupport(client, true);
mockServerSideSupport(client, ServerSupport.Stable);
client.sendReceipt(threadEvent, ReceiptType.Read, {});

await httpBackend.flushAllExpected();
await flushPromises();
});

it("sends an unthreaded receipt", async () => {
httpBackend.when(
"POST", encodeUri("/rooms/$roomId/receipt/$receiptType/$eventId", {
$roomId: ROOM_ID,
$receiptType: ReceiptType.Read,
$eventId: threadEvent.getId()!,
}),
).check((request) => {
expect(request.data.thread_id).toBeUndefined();
}).respond(200, {});

mockServerSideSupport(client, ServerSupport.Stable);
client.sendReadReceipt(threadEvent, ReceiptType.Read, true);

await httpBackend.flushAllExpected();
await flushPromises();
});

it("sends a room read receipt", async () => {
httpBackend.when(
"POST", encodeUri("/rooms/$roomId/receipt/$receiptType/$eventId", {
Expand All @@ -121,7 +133,7 @@ describe("Read receipt", () => {
expect(request.data.thread_id).toEqual(MAIN_ROOM_TIMELINE);
}).respond(200, {});

mockServerSideSupport(client, true);
mockServerSideSupport(client, ServerSupport.Stable);
client.sendReceipt(roomEvent, ReceiptType.Read, {});

await httpBackend.flushAllExpected();
Expand All @@ -139,7 +151,7 @@ describe("Read receipt", () => {
expect(request.data.thread_id).toBeUndefined();
}).respond(200, {});

mockServerSideSupport(client, false);
mockServerSideSupport(client, ServerSupport.Unsupported);
client.sendReceipt(threadEvent, ReceiptType.Read, {});

await httpBackend.flushAllExpected();
Expand All @@ -157,7 +169,7 @@ describe("Read receipt", () => {
expect(request.data).toEqual({});
}).respond(200, {});

mockServerSideSupport(client, false);
mockServerSideSupport(client, ServerSupport.Unsupported);
client.sendReceipt(threadEvent, ReceiptType.Read, undefined);

await httpBackend.flushAllExpected();
Expand Down
18 changes: 12 additions & 6 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4588,13 +4588,15 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
* @param {ReceiptType} receiptType The kind of receipt e.g. "m.read". Other than
* ReceiptType.Read are experimental!
* @param {object} body Additional content to send alongside the receipt.
* @param {boolean} unthreaded An unthreaded receipt will clear room+thread notifications
* @return {Promise} Resolves: to an empty object {}
* @return {module:http-api.MatrixError} Rejects: with an error response.
*/
public async sendReceipt(
event: MatrixEvent,
receiptType: ReceiptType,
body: any,
unthreaded = false,
): Promise<{}> {
if (this.isGuest()) {
return Promise.resolve({}); // guests cannot send receipts so don't bother.
Expand All @@ -4606,12 +4608,15 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
$eventId: event.getId()!,
});

// TODO: Add a check for which spec version this will be released in
if (await this.doesServerSupportUnstableFeature("org.matrix.msc3771")) {
const supportsThreadRR = this.canSupport.get(Feature.ThreadUnreadNotifications) !== ServerSupport.Unsupported;
if (supportsThreadRR && !unthreaded) {
const isThread = !!event.threadRootId;
body.thread_id = isThread
? event.threadRootId
: MAIN_ROOM_TIMELINE;
body = {
...body,
thread_id: isThread
? event.threadRootId
: MAIN_ROOM_TIMELINE,
};
}

const promise = this.http.authedRequest<{}>(Method.Post, path, undefined, body || {});
Expand All @@ -4633,6 +4638,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
public async sendReadReceipt(
event: MatrixEvent | null,
receiptType = ReceiptType.Read,
unthreaded = false,
): Promise<{} | undefined> {
if (!event) return;
const eventId = event.getId()!;
Expand All @@ -4641,7 +4647,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
throw new Error(`Cannot set read receipt to a pending event (${eventId})`);
}

return this.sendReceipt(event, receiptType, {});
return this.sendReceipt(event, receiptType, {}, unthreaded);
}

/**
Expand Down