Skip to content

Commit

Permalink
Show the local echo in previews (#12451)
Browse files Browse the repository at this point in the history
* show the local echo in previews

* a bit more coverage
  • Loading branch information
langleyd authored Apr 24, 2024
1 parent 158e111 commit 644bf78
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 4 deletions.
19 changes: 17 additions & 2 deletions src/stores/room-list/MessagePreviewStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

import { Room, RelationType, MatrixEvent, Thread, M_POLL_START } from "matrix-js-sdk/src/matrix";
import { Room, RelationType, MatrixEvent, Thread, M_POLL_START, RoomEvent } from "matrix-js-sdk/src/matrix";
import { isNullOrUndefined } from "matrix-js-sdk/src/utils";

import { ActionPayload } from "../../dispatcher/payloads";
Expand Down Expand Up @@ -186,7 +186,7 @@ export class MessagePreviewStore extends AsyncStoreWithClient<IState> {
}

private async generatePreview(room: Room, tagId?: TagID): Promise<void> {
const events = [...room.getLiveTimeline().getEvents()];
const events = [...room.getLiveTimeline().getEvents(), ...room.getPendingEvents()];

// add last reply from each thread
room.getThreads().forEach((thread: Thread): void => {
Expand Down Expand Up @@ -279,4 +279,19 @@ export class MessagePreviewStore extends AsyncStoreWithClient<IState> {
await this.generatePreview(room, TAG_ANY);
}
}

protected async onReady(): Promise<void> {
if (!this.matrixClient) return;
this.matrixClient.on(RoomEvent.LocalEchoUpdated, this.onLocalEchoUpdated);
}

protected async onNotReady(): Promise<void> {
if (!this.matrixClient) return;
this.matrixClient.off(RoomEvent.LocalEchoUpdated, this.onLocalEchoUpdated);
}

protected onLocalEchoUpdated = async (ev: MatrixEvent, room: Room): Promise<void> => {
if (!this.previews.has(room.roomId)) return;
await this.generatePreview(room, TAG_ANY);
};
}
99 changes: 97 additions & 2 deletions test/stores/room-list/MessagePreviewStore-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,16 @@ limitations under the License.
*/

import { Mocked, mocked } from "jest-mock";
import { EventTimeline, EventType, MatrixClient, MatrixEvent, RelationType, Room } from "matrix-js-sdk/src/matrix";
import {
EventStatus,
EventTimeline,
EventType,
MatrixClient,
MatrixEvent,
PendingEventOrdering,
RelationType,
Room,
} from "matrix-js-sdk/src/matrix";

import { MessagePreviewStore } from "../../../src/stores/room-list/MessagePreviewStore";
import { mkEvent, mkMessage, mkReaction, setupAsyncStoreWithClient, stubClient } from "../../test-utils";
Expand All @@ -25,6 +34,7 @@ import { mkThread } from "../../test-utils/threads";
describe("MessagePreviewStore", () => {
let client: Mocked<MatrixClient>;
let room: Room;
let nonRenderedRoom: Room;
let store: MessagePreviewStore;

async function addEvent(
Expand All @@ -46,9 +56,35 @@ describe("MessagePreviewStore", () => {
}
}

async function addPendingEvent(
store: MessagePreviewStore,
room: Room,
event: MatrixEvent,
fireAction = true,
): Promise<void> {
room.addPendingEvent(event, "txid");
if (fireAction) {
// @ts-ignore private access
await store.onLocalEchoUpdated(event, room);
}
}

async function updatePendingEvent(event: MatrixEvent, eventStatus: EventStatus, fireAction = true): Promise<void> {
room.updatePendingEvent(event, eventStatus);
if (fireAction) {
// @ts-ignore private access
await store.onLocalEchoUpdated(event, room);
}
}

beforeEach(async () => {
client = mocked(stubClient());
room = new Room("!roomId:server", client, client.getSafeUserId());
room = new Room("!roomId:server", client, client.getSafeUserId(), {
pendingEventOrdering: PendingEventOrdering.Detached,
});
nonRenderedRoom = new Room("!roomId2:server", client, client.getSafeUserId(), {
pendingEventOrdering: PendingEventOrdering.Detached,
});
mocked(client.getRoom).mockReturnValue(room);

store = MessagePreviewStore.testInstance();
Expand Down Expand Up @@ -286,4 +322,63 @@ describe("MessagePreviewStore", () => {
expect(preview?.isThreadReply).toBe(false);
expect(preview?.text).toContain("You reacted 🙃 to root event message");
});

it("should handle local echos correctly", async () => {
const firstMessage = mkMessage({
user: "@sender:server",
event: true,
room: room.roomId,
msg: "First message",
});

await addEvent(store, room, firstMessage);

expect((await store.getPreviewForRoom(room, DefaultTagID.Untagged))?.text).toMatchInlineSnapshot(
`"@sender:server: First message"`,
);

const secondMessage = mkMessage({
user: "@sender:server",
event: true,
room: room.roomId,
msg: "Second message",
});
secondMessage.status = EventStatus.NOT_SENT;

await addPendingEvent(store, room, secondMessage);

expect((await store.getPreviewForRoom(room, DefaultTagID.Untagged))?.text).toMatchInlineSnapshot(
`"@sender:server: Second message"`,
);

await updatePendingEvent(secondMessage, EventStatus.CANCELLED);

expect((await store.getPreviewForRoom(room, DefaultTagID.Untagged))?.text).toMatchInlineSnapshot(
`"@sender:server: First message"`,
);
});

it("should not generate previews for rooms not rendered", async () => {
const firstMessage = mkMessage({
user: "@sender:server",
event: true,
room: nonRenderedRoom.roomId,
msg: "First message",
});

await addEvent(store, room, firstMessage);

const secondMessage = mkMessage({
user: "@sender:server",
event: true,
room: nonRenderedRoom.roomId,
msg: "Second message",
});
secondMessage.status = EventStatus.NOT_SENT;

await addPendingEvent(store, room, secondMessage);

// @ts-ignore private access
expect(store.previews.has(nonRenderedRoom.roomId)).toBeFalsy();
});
});

0 comments on commit 644bf78

Please sign in to comment.