mirror of
https://github.com/vector-im/element-web.git
synced 2024-11-28 03:18:32 +08:00
8b7f49e74e
* Rewrite doesRoomOrThreadHaveUnreadMessages to use the receipt rewrite from js-sdk * Remove unit tests that rely on receipt timestamps Previously, if we found a receipt for an unknown event, we would use the receipt timestamp and declare all events before that time to be read. Now, we ignore such "dangling" receipts until we find the event they refer to. This new behaviour is more correct, but does lead to more messages being considered unread. This commit deletes tests that checked for the old behaviour. * Check for a missing thread in determineUnreadState * Fix incorrect way to find room timeline * More realistic test setup to support new receipt code * Update snapshot to expect a room to be unread when there are no receipts * Formatting fixes * Update snapshot to show menu and notif button * Disable some flaky tests * Disable some flaky tests * Fix test to make a threaded receipt for an event that is actually in the thread --------- Co-authored-by: Florian Duros <florianduros@element.io> Co-authored-by: Florian Duros <florian.duros@ormaz.fr>
171 lines
4.8 KiB
TypeScript
171 lines
4.8 KiB
TypeScript
/*
|
|
Copyright 2022 The Matrix.org Foundation C.I.C.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
import { MatrixClient, MatrixEvent, MatrixEventEvent, RelationType, Room, Thread } from "matrix-js-sdk/src/matrix";
|
|
|
|
import { mkMessage, MessageEventProps } from "./test-utils";
|
|
|
|
export const makeThreadEvent = ({
|
|
rootEventId,
|
|
replyToEventId,
|
|
...props
|
|
}: MessageEventProps & {
|
|
rootEventId: string;
|
|
replyToEventId: string;
|
|
}): MatrixEvent =>
|
|
mkMessage({
|
|
...props,
|
|
relatesTo: {
|
|
event_id: rootEventId,
|
|
rel_type: "m.thread",
|
|
["m.in_reply_to"]: {
|
|
event_id: replyToEventId,
|
|
},
|
|
},
|
|
});
|
|
|
|
type MakeThreadEventsProps = {
|
|
roomId: Room["roomId"];
|
|
// root message user id
|
|
authorId: string;
|
|
// user ids of thread replies
|
|
// cycled through until thread length is fulfilled
|
|
participantUserIds: string[];
|
|
// number of messages in the thread, root message included
|
|
// optional, default 2
|
|
length?: number;
|
|
ts?: number;
|
|
// provide to set current_user_participated accurately
|
|
currentUserId?: string;
|
|
};
|
|
|
|
export const makeThreadEvents = ({
|
|
roomId,
|
|
authorId,
|
|
participantUserIds,
|
|
length = 2,
|
|
ts = 1,
|
|
currentUserId,
|
|
}: MakeThreadEventsProps): { rootEvent: MatrixEvent; events: MatrixEvent[] } => {
|
|
const rootEvent = mkMessage({
|
|
user: authorId,
|
|
event: true,
|
|
room: roomId,
|
|
msg: "root event message " + Math.random(),
|
|
ts,
|
|
});
|
|
|
|
const rootEventId = rootEvent.getId()!;
|
|
const events = [rootEvent];
|
|
|
|
for (let i = 1; i < length; i++) {
|
|
const prevEvent = events[i - 1];
|
|
const replyToEventId = prevEvent.getId()!;
|
|
const user = participantUserIds[i % participantUserIds.length];
|
|
events.push(
|
|
makeThreadEvent({
|
|
user,
|
|
room: roomId,
|
|
event: true,
|
|
msg: `reply ${i} by ${user}`,
|
|
rootEventId,
|
|
replyToEventId,
|
|
// replies are 1ms after each other
|
|
ts: ts + i,
|
|
}),
|
|
);
|
|
}
|
|
|
|
rootEvent.setUnsigned({
|
|
"m.relations": {
|
|
[RelationType.Thread]: {
|
|
latest_event: events[events.length - 1],
|
|
count: length,
|
|
current_user_participated: [...participantUserIds, authorId].includes(currentUserId!),
|
|
},
|
|
},
|
|
});
|
|
|
|
return { rootEvent, events };
|
|
};
|
|
|
|
type MakeThreadProps = {
|
|
room: Room;
|
|
client: MatrixClient;
|
|
authorId: string;
|
|
participantUserIds: string[];
|
|
length?: number;
|
|
ts?: number;
|
|
};
|
|
|
|
/**
|
|
* Create a thread but don't actually populate it with events - see
|
|
* populateThread for what you probably want to do.
|
|
*
|
|
* Leaving this here in case it is needed by some people, but I (andyb) would
|
|
* expect us to move to use populateThread exclusively.
|
|
*/
|
|
export const mkThread = ({
|
|
room,
|
|
client,
|
|
authorId,
|
|
participantUserIds,
|
|
length = 2,
|
|
ts = 1,
|
|
}: MakeThreadProps): { thread: Thread; rootEvent: MatrixEvent; events: MatrixEvent[] } => {
|
|
const { rootEvent, events } = makeThreadEvents({
|
|
roomId: room.roomId,
|
|
authorId,
|
|
participantUserIds,
|
|
length,
|
|
ts,
|
|
currentUserId: client.getUserId()!,
|
|
});
|
|
expect(rootEvent).toBeTruthy();
|
|
|
|
for (const evt of events) {
|
|
room?.reEmitter.reEmit(evt, [MatrixEventEvent.BeforeRedaction]);
|
|
}
|
|
|
|
const thread = room.createThread(rootEvent.getId()!, rootEvent, events, true);
|
|
|
|
return { thread, rootEvent, events };
|
|
};
|
|
|
|
/**
|
|
* Create a thread, and make sure the events added to the thread and the room's
|
|
* timeline as if they came in via sync.
|
|
*
|
|
* Note that mkThread doesn't actually add the events properly to the room.
|
|
*/
|
|
export const populateThread = async ({
|
|
room,
|
|
client,
|
|
authorId,
|
|
participantUserIds,
|
|
length = 2,
|
|
ts = 1,
|
|
}: MakeThreadProps): Promise<{ thread: Thread; rootEvent: MatrixEvent; events: MatrixEvent[] }> => {
|
|
const ret = mkThread({ room, client, authorId, participantUserIds, length, ts });
|
|
|
|
// So that we do not have to mock the thread loading, tell the thread
|
|
// that it is already loaded, and send the events again to the room
|
|
// so they are added to the thread timeline.
|
|
ret.thread.initialEventsFetched = true;
|
|
await room.addLiveEvents(ret.events);
|
|
return ret;
|
|
};
|