Open right panel timeline when jumping to event with maximised widget (#31626)

* Open right panel timeline when jumping to event with maximised widget

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Add test

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Fix types & update snapshot

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

---------

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
Michael Telatynski
2026-01-05 09:36:55 +00:00
committed by GitHub
parent cf7bf71d01
commit 885305aa46
3 changed files with 44 additions and 15 deletions
+9
View File
@@ -766,6 +766,15 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
newState.search = undefined; newState.search = undefined;
} }
if (
room &&
this.getMainSplitContentType(room) !== MainSplitContentType.Timeline &&
newState.initialEventId !== this.state.initialEventId
) {
// Ensure the right panel timeline is open to show the linked event
this.context.rightPanelStore.setCard({ phase: RightPanelPhases.Timeline }, true, room.roomId);
}
this.setState(newState as IRoomState); this.setState(newState as IRoomState);
// At this point, newState.roomId could be null (e.g. the alias might not // At this point, newState.roomId could be null (e.g. the alias might not
// have been resolved yet) so anything called here must handle this case. // have been resolved yet) so anything called here must handle this case.
@@ -22,32 +22,32 @@ import {
RoomStateEvent, RoomStateEvent,
SearchResult, SearchResult,
} from "matrix-js-sdk/src/matrix"; } from "matrix-js-sdk/src/matrix";
import { type CryptoApi, UserVerificationStatus, CryptoEvent } from "matrix-js-sdk/src/crypto-api"; import { type CryptoApi, CryptoEvent, UserVerificationStatus } from "matrix-js-sdk/src/crypto-api";
import { KnownMembership } from "matrix-js-sdk/src/types"; import { KnownMembership } from "matrix-js-sdk/src/types";
import { import {
fireEvent,
render,
screen,
type RenderResult,
waitForElementToBeRemoved,
waitFor,
act, act,
cleanup, cleanup,
fireEvent,
render,
type RenderResult,
screen,
waitFor,
waitForElementToBeRemoved,
} from "jest-matrix-react"; } from "jest-matrix-react";
import userEvent from "@testing-library/user-event"; import userEvent from "@testing-library/user-event";
import { import {
stubClient, createTestClient,
mockPlatformPeg, emitPromise,
unmockPlatformPeg, filterConsole,
flushPromises, flushPromises,
mkEvent, mkEvent,
setupAsyncStoreWithClient,
filterConsole,
mkRoomMemberJoinEvent, mkRoomMemberJoinEvent,
mkThirdPartyInviteEvent, mkThirdPartyInviteEvent,
emitPromise, mockPlatformPeg,
createTestClient, setupAsyncStoreWithClient,
stubClient,
unmockPlatformPeg,
untilDispatch, untilDispatch,
} from "../../../test-utils"; } from "../../../test-utils";
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg"; import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
@@ -628,6 +628,26 @@ describe("RoomView", () => {
const { asFragment } = await mountRoomView(); const { asFragment } = await mountRoomView();
expect(asFragment()).toMatchSnapshot(); expect(asFragment()).toMatchSnapshot();
}); });
it("should open timeline card when navigating to permalink", async () => {
jest.spyOn(room, "getMyMembership").mockReturnValue(KnownMembership.Join);
await mountRoomView();
stores.rightPanelStore.setCard({ phase: RightPanelPhases.RoomSummary });
expect(stores.rightPanelStore.isOpen).toEqual(true);
expect(stores.rightPanelStore.currentCard.phase).not.toEqual(RightPanelPhases.Timeline);
await stores.roomViewStore.viewRoom({
action: Action.ViewRoom,
room_id: stores.roomViewStore.getRoomId()!,
event_id: "$eventId",
metricsTrigger: undefined,
});
expect(stores.rightPanelStore.isOpen).toEqual(true);
expect(stores.rightPanelStore.currentCard.phase).toEqual(RightPanelPhases.Timeline);
});
}); });
describe("for a local room", () => { describe("for a local room", () => {
@@ -385,7 +385,7 @@ exports[`RoomView for a local room in state NEW should match the snapshot 1`] =
> >
<svg <svg
aria-label="Messages in this room are not end-to-end encrypted" aria-label="Messages in this room are not end-to-end encrypted"
aria-labelledby="_r_o1_" aria-labelledby="_r_qd_"
class="mx_E2EIcon mx_MessageComposer_e2eIcon" class="mx_E2EIcon mx_MessageComposer_e2eIcon"
color="var(--cpd-color-icon-info-primary)" color="var(--cpd-color-icon-info-primary)"
fill="currentColor" fill="currentColor"