Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to send unthreaded receipt #2878

Merged
merged 1 commit into from
Nov 14, 2022
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
t3chguy marked this conversation as resolved.
Show resolved Hide resolved
* @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