From ef412b9fe67800453a872f94a1763eb60782c43a Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 4 Dec 2023 10:49:03 +0000 Subject: [PATCH 1/7] Fix editing event from search room view Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/RoomView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx index 2689fab9d47..a98bd25900a 100644 --- a/src/components/structures/RoomView.tsx +++ b/src/components/structures/RoomView.tsx @@ -1209,7 +1209,7 @@ export class RoomView extends React.Component { // Quit early if we're trying to edit events in wrong rendering context if (payload.timelineRenderingType !== this.state.timelineRenderingType) return; const editState = payload.event ? new EditorStateTransfer(payload.event) : undefined; - this.setState({ editState }, () => { + this.setState({ editState, search: undefined }, () => { if (payload.event) { this.messagePanel?.scrollToEventIfNeeded(payload.event.getId()); } From b86911701ebdcf63c7de96f0cb4bbb620b7a5234 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 5 Dec 2023 10:05:57 +0000 Subject: [PATCH 2/7] Iterate Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/RoomView.tsx | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx index 36c8fd58c52..e8209a8aa23 100644 --- a/src/components/structures/RoomView.tsx +++ b/src/components/structures/RoomView.tsx @@ -186,6 +186,9 @@ export interface IRoomState { initialEventScrollIntoView?: boolean; replyToEvent?: MatrixEvent; numUnreadMessages: number; + /** + * The state of an ongoing search if there is one. + */ search?: ISearchInfo; callState?: CallState; activeCall: Call | null; @@ -1209,11 +1212,18 @@ export class RoomView extends React.Component { // Quit early if we're trying to edit events in wrong rendering context if (payload.timelineRenderingType !== this.state.timelineRenderingType) return; const editState = payload.event ? new EditorStateTransfer(payload.event) : undefined; - this.setState({ editState, search: undefined }, () => { - if (payload.event) { - this.messagePanel?.scrollToEventIfNeeded(payload.event.getId()); - } - }); + this.setState( + { + editState, + // Clear the search state as we don't consume editState in SearchRoomView + search: undefined, + }, + () => { + if (payload.event) { + this.messagePanel?.scrollToEventIfNeeded(payload.event.getId()); + } + }, + ); break; } From 81f6052d4f00e4ca178601d7720082ede3fb2d07 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 5 Dec 2023 10:10:30 +0000 Subject: [PATCH 3/7] Handle different room for all rooms search case Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/RoomView.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx index e8209a8aa23..08fd1dbdd3e 100644 --- a/src/components/structures/RoomView.tsx +++ b/src/components/structures/RoomView.tsx @@ -1211,6 +1211,17 @@ export class RoomView extends React.Component { case Action.EditEvent: { // Quit early if we're trying to edit events in wrong rendering context if (payload.timelineRenderingType !== this.state.timelineRenderingType) return; + if (payload.event && payload.event.getRoomId() !== this.state.roomId) { + // If the event is in a different room, we need to view that room first + dis.dispatch({ + action: Action.ViewRoom, + room_id: payload.even?.getRoomId(), + metricsTrigger: "MessageSearch", + deferred_action: payload, + }); + return; + } + const editState = payload.event ? new EditorStateTransfer(payload.event) : undefined; this.setState( { From 411ac0a52a1bf7b5f4ef451bb3ca5dff8b76c576 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 5 Dec 2023 13:23:21 +0000 Subject: [PATCH 4/7] Iterate Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/RoomView.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx index 08fd1dbdd3e..574d329b2fa 100644 --- a/src/components/structures/RoomView.tsx +++ b/src/components/structures/RoomView.tsx @@ -1212,11 +1212,11 @@ export class RoomView extends React.Component { // Quit early if we're trying to edit events in wrong rendering context if (payload.timelineRenderingType !== this.state.timelineRenderingType) return; if (payload.event && payload.event.getRoomId() !== this.state.roomId) { - // If the event is in a different room, we need to view that room first + // If the event is in a different room (e.g. all rooms search), we need to view that room first dis.dispatch({ action: Action.ViewRoom, - room_id: payload.even?.getRoomId(), - metricsTrigger: "MessageSearch", + room_id: payload.event?.getRoomId(), + metricsTrigger: undefined, deferred_action: payload, }); return; @@ -1226,7 +1226,7 @@ export class RoomView extends React.Component { this.setState( { editState, - // Clear the search state as we don't consume editState in SearchRoomView + // Close any ongoing search as the RoomSearchView doesn't pass editState and thus won't render the edit composer search: undefined, }, () => { From b0bdaa0a454a1bf0cd913faa5233d5d0592d2247 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 6 Dec 2023 13:02:38 +0000 Subject: [PATCH 5/7] Iterate Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/RoomView.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx index 574d329b2fa..d8904692a8f 100644 --- a/src/components/structures/RoomView.tsx +++ b/src/components/structures/RoomView.tsx @@ -1212,10 +1212,11 @@ export class RoomView extends React.Component { // Quit early if we're trying to edit events in wrong rendering context if (payload.timelineRenderingType !== this.state.timelineRenderingType) return; if (payload.event && payload.event.getRoomId() !== this.state.roomId) { - // If the event is in a different room (e.g. all rooms search), we need to view that room first + // If the event is in a different room (e.g. because the event to be edited is being displayed + // in the results of an all-rooms search), we need to view that room first. dis.dispatch({ action: Action.ViewRoom, - room_id: payload.event?.getRoomId(), + room_id: payload.event.getRoomId(), metricsTrigger: undefined, deferred_action: payload, }); @@ -1226,7 +1227,9 @@ export class RoomView extends React.Component { this.setState( { editState, - // Close any ongoing search as the RoomSearchView doesn't pass editState and thus won't render the edit composer + // If a search is active (implying that the "edit" button has been pressed on one of the + // events in the search result), we need to close that search, because RoomSearchView + // doesn't handle editing and won't render the composer. search: undefined, }, () => { From 1024b981d948260fddb7852495695a9040717609 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 19 Dec 2023 14:28:30 +0000 Subject: [PATCH 6/7] Add tests Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- test/components/structures/RoomView-test.tsx | 66 +++++++++++++++++++- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/test/components/structures/RoomView-test.tsx b/test/components/structures/RoomView-test.tsx index 29a0f51c032..52fa9f0c6a7 100644 --- a/test/components/structures/RoomView-test.tsx +++ b/test/components/structures/RoomView-test.tsx @@ -26,9 +26,12 @@ import { MatrixError, RoomStateEvent, MatrixEvent, + SearchResult, + IEvent, } from "matrix-js-sdk/src/matrix"; import { MEGOLM_ALGORITHM } from "matrix-js-sdk/src/crypto/olmlib"; -import { fireEvent, render, screen, RenderResult } from "@testing-library/react"; +import { fireEvent, render, screen, RenderResult, waitForElementToBeRemoved, waitFor } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; import { stubClient, @@ -60,12 +63,13 @@ import { LocalRoom, LocalRoomState } from "../../../src/models/LocalRoom"; import { DirectoryMember } from "../../../src/utils/direct-messages"; import { createDmLocalRoom } from "../../../src/utils/dm/createDmLocalRoom"; import { UPDATE_EVENT } from "../../../src/stores/AsyncStore"; -import { SdkContextClass, SDKContext } from "../../../src/contexts/SDKContext"; +import { SDKContext, SdkContextClass } from "../../../src/contexts/SDKContext"; import VoipUserMapper from "../../../src/VoipUserMapper"; import WidgetUtils from "../../../src/utils/WidgetUtils"; import { WidgetType } from "../../../src/widgets/WidgetType"; import WidgetStore from "../../../src/stores/WidgetStore"; import { ViewRoomErrorPayload } from "../../../src/dispatcher/payloads/ViewRoomErrorPayload"; +import { SearchScope } from "../../../src/components/views/rooms/SearchBar"; const RoomView = wrapInMatrixClientContext(_RoomView); @@ -591,4 +595,62 @@ describe("RoomView", () => { await mountRoomView(); expect(dis.dispatch).toHaveBeenCalledWith({ action: Action.RoomLoaded }); }); + + it("should close search results when edit is clicked", async () => { + room.getMyMembership = jest.fn().mockReturnValue("join"); + + const eventMapper = (obj: Partial) => new MatrixEvent(obj); + + const roomViewRef = createRef<_RoomView>(); + const { container, getByText, findByLabelText } = await mountRoomView(roomViewRef); + // @ts-ignore - triggering a search organically is a lot of work + roomViewRef.current!.setState({ + search: { + searchId: 1, + roomId: room.roomId, + term: "search term", + scope: SearchScope.Room, + promise: Promise.resolve({ + results: [ + SearchResult.fromJson( + { + rank: 1, + result: { + content: { + body: "search term", + msgtype: "m.text", + }, + type: "m.room.message", + event_id: "$eventId", + sender: cli.getSafeUserId(), + origin_server_ts: 123456789, + room_id: room.roomId, + }, + context: { + events_before: [], + events_after: [], + profile_info: {}, + }, + }, + eventMapper, + ), + ], + highlights: [], + count: 1, + }), + inProgress: false, + count: 1, + }, + }); + + await waitFor(() => { + expect(container.querySelector(".mx_RoomView_searchResultsPanel")).toBeVisible(); + }); + const prom = waitForElementToBeRemoved(() => container.querySelector(".mx_RoomView_searchResultsPanel")); + + await userEvent.hover(getByText("search term")); + await userEvent.click(await findByLabelText("Edit")); + + await prom; + }); }); From 982147d3be291d1beb28ae891b8be349c9f9f5ba Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 19 Dec 2023 14:56:15 +0000 Subject: [PATCH 7/7] Increase coverage Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- test/components/structures/RoomView-test.tsx | 61 ++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/test/components/structures/RoomView-test.tsx b/test/components/structures/RoomView-test.tsx index aaffe72361e..6d4dadbc8f7 100644 --- a/test/components/structures/RoomView-test.tsx +++ b/test/components/structures/RoomView-test.tsx @@ -647,4 +647,65 @@ describe("RoomView", () => { await prom; }); + + it("should switch rooms when edit is clicked on a search result for a different room", async () => { + const room2 = new Room(`!${roomCount++}:example.org`, cli, "@alice:example.org"); + rooms.set(room2.roomId, room2); + + room.getMyMembership = jest.fn().mockReturnValue("join"); + + const eventMapper = (obj: Partial) => new MatrixEvent(obj); + + const roomViewRef = createRef<_RoomView>(); + const { container, getByText, findByLabelText } = await mountRoomView(roomViewRef); + // @ts-ignore - triggering a search organically is a lot of work + roomViewRef.current!.setState({ + search: { + searchId: 1, + roomId: room.roomId, + term: "search term", + scope: SearchScope.All, + promise: Promise.resolve({ + results: [ + SearchResult.fromJson( + { + rank: 1, + result: { + content: { + body: "search term", + msgtype: "m.text", + }, + type: "m.room.message", + event_id: "$eventId", + sender: cli.getSafeUserId(), + origin_server_ts: 123456789, + room_id: room2.roomId, + }, + context: { + events_before: [], + events_after: [], + profile_info: {}, + }, + }, + eventMapper, + ), + ], + highlights: [], + count: 1, + }), + inProgress: false, + count: 1, + }, + }); + + await waitFor(() => { + expect(container.querySelector(".mx_RoomView_searchResultsPanel")).toBeVisible(); + }); + const prom = untilDispatch(Action.ViewRoom, dis); + + await userEvent.hover(getByText("search term")); + await userEvent.click(await findByLabelText("Edit")); + + await expect(prom).resolves.toEqual(expect.objectContaining({ room_id: room2.roomId })); + }); });