Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Show a tile for an unloaded predecessor room if it has via_servers #10483

Merged
merged 21 commits into from
Apr 12, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
20dc6df
Improve typing in constructor of RoomPermalinkCreator
andybalaam Mar 30, 2023
c6736e0
Provide via servers if present when navigating to predecessor room fr…
andybalaam Mar 30, 2023
0075c0c
Show an error tile when the predecessor room is not found
andybalaam Mar 30, 2023
edb38a8
Test for MatrixToPermalinkConstructor.forRoom
andybalaam Mar 30, 2023
44762c9
Test for MatrixToPermalinkConstructor.forEvent
andybalaam Mar 30, 2023
9767dea
Display a tile for predecessor event if it contains via servers
andybalaam Mar 30, 2023
21c8341
Fix missing case where event id is provided as well as via servers
andybalaam Apr 3, 2023
849b45b
Refactor RoomPredecessor tests
andybalaam Apr 3, 2023
8aa996c
Return lost filterConsole to its home
andybalaam Apr 3, 2023
b8cec98
Comments for IState in AdvancedRoomSettingsTab
andybalaam Apr 3, 2023
7db8b26
Explain why we might render a tile even without prevRoom
andybalaam Apr 4, 2023
eba4adb
Guess the old room's via servers if they are not provided
andybalaam Apr 4, 2023
5a110fd
Fix TypeScript errors
andybalaam Apr 4, 2023
1ab7740
Adjust regular expression (hopefully) to avoid potential catastrophic…
andybalaam Apr 5, 2023
7bf4c59
Merge branch 'develop' into andybalaam/viaservers-for-dynamic-predece…
andybalaam Apr 5, 2023
eeb92e6
Another attempt at avoiding super-liner regex performance
andybalaam Apr 5, 2023
475f629
Merge branch 'develop' into andybalaam/viaservers-for-dynamic-predece…
t3chguy Apr 5, 2023
2f80b71
Tests for guessServerNameFromRoomId and better implementation
andybalaam Apr 12, 2023
fb89367
Merge branch 'develop' into andybalaam/viaservers-for-dynamic-predece…
andybalaam Apr 12, 2023
7f1ac7a
Further attempt to prevent backtracking
andybalaam Apr 12, 2023
8430ced
Merge branch 'develop' into andybalaam/viaservers-for-dynamic-predece…
andybalaam Apr 12, 2023
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
55 changes: 45 additions & 10 deletions src/components/views/messages/RoomPredecessorTile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ limitations under the License.
import React, { useCallback, useContext } from "react";
import { logger } from "matrix-js-sdk/src/logger";
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { Room } from "matrix-js-sdk/src/matrix";

import dis from "../../../dispatcher/dispatcher";
import { Action } from "../../../dispatcher/actions";
Expand All @@ -29,6 +30,7 @@ import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
import RoomContext from "../../../contexts/RoomContext";
import { useRoomState } from "../../../hooks/useRoomState";
import SettingsStore from "../../../settings/SettingsStore";
import MatrixToPermalinkConstructor from "../../../utils/permalinks/MatrixToPermalinkConstructor";

interface IProps {
/** The m.room.create MatrixEvent that this tile represents */
Expand Down Expand Up @@ -86,18 +88,32 @@ export const RoomPredecessorTile: React.FC<IProps> = ({ mxEvent, timestamp }) =>
}

const prevRoom = MatrixClientPeg.get().getRoom(predecessor.roomId);
if (!prevRoom) {

// We need either the previous room, or some servers to find it with.
// Otherwise, we must bail out here
andybalaam marked this conversation as resolved.
Show resolved Hide resolved
if (!prevRoom && !predecessor.viaServers) {
andybalaam marked this conversation as resolved.
Show resolved Hide resolved
logger.warn(`Failed to find predecessor room with id ${predecessor.roomId}`);
return <></>;
}
const permalinkCreator = new RoomPermalinkCreator(prevRoom, predecessor.roomId);
permalinkCreator.load();
let predecessorPermalink: string;
if (predecessor.eventId) {
predecessorPermalink = permalinkCreator.forEvent(predecessor.eventId);
} else {
predecessorPermalink = permalinkCreator.forRoom();
return (
<EventTileBubble
className="mx_CreateEvent"
title={_t("This room is a continuation of another conversation.")}
timestamp={timestamp}
>
<div className="mx_EventTile_body">
<span className="mx_EventTile_tileError">
andybalaam marked this conversation as resolved.
Show resolved Hide resolved
{_t("Can't find the old version of this room (room id: %(roomId)s).", {
MadLittleMods marked this conversation as resolved.
Show resolved Hide resolved
roomId: predecessor.roomId,
})}
</span>
</div>
</EventTileBubble>
);
}
andybalaam marked this conversation as resolved.
Show resolved Hide resolved

const predecessorPermalink = prevRoom
? createLinkWithRoom(prevRoom, predecessor.roomId, predecessor.eventId)
: createLinkWithoutRoom(predecessor.roomId, predecessor.viaServers);
andybalaam marked this conversation as resolved.
Show resolved Hide resolved

const link = (
<a href={predecessorPermalink} onClick={onLinkClicked}>
{_t("Click here to see older messages.")}
Expand All @@ -112,4 +128,23 @@ export const RoomPredecessorTile: React.FC<IProps> = ({ mxEvent, timestamp }) =>
timestamp={timestamp}
/>
);

function createLinkWithRoom(room: Room, roomId: string, eventId?: string): string {
const permalinkCreator = new RoomPermalinkCreator(room, roomId);
permalinkCreator.load();
if (eventId) {
return permalinkCreator.forEvent(eventId);
} else {
return permalinkCreator.forRoom();
}
}

function createLinkWithoutRoom(roomId: string, viaServers: string[], eventId?: string): string {
const matrixToPermalinkConstructor = new MatrixToPermalinkConstructor();
if (eventId) {
return matrixToPermalinkConstructor.forEvent(roomId, eventId, viaServers);
} else {
return matrixToPermalinkConstructor.forRoom(roomId, viaServers);
}
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ interface IState {
upgradeRecommendation?: IRecommendedVersion;
oldRoomId?: string;
oldEventId?: string;
oldViaServers?: string[];
andybalaam marked this conversation as resolved.
Show resolved Hide resolved
upgraded?: boolean;
}

Expand All @@ -65,6 +66,7 @@ export default class AdvancedRoomSettingsTab extends React.Component<IProps, ISt
if (predecessor) {
additionalStateChanges.oldRoomId = predecessor.roomId;
additionalStateChanges.oldEventId = predecessor.eventId;
additionalStateChanges.oldViaServers = predecessor.viaServers;
}

this.setState({
Expand All @@ -88,6 +90,7 @@ export default class AdvancedRoomSettingsTab extends React.Component<IProps, ISt
action: Action.ViewRoom,
room_id: this.state.oldRoomId,
event_id: this.state.oldEventId,
via_servers: this.state.oldViaServers,
metricsTrigger: "WebPredecessorSettings",
metricsViaKeyboard: e.type !== "click",
});
Expand Down
3 changes: 2 additions & 1 deletion src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
Expand Up @@ -2464,8 +2464,9 @@
"%(senderDisplayName)s changed the avatar for %(roomName)s": "%(senderDisplayName)s changed the avatar for %(roomName)s",
"%(senderDisplayName)s removed the room avatar.": "%(senderDisplayName)s removed the room avatar.",
"%(senderDisplayName)s changed the room avatar to <img/>": "%(senderDisplayName)s changed the room avatar to <img/>",
"Click here to see older messages.": "Click here to see older messages.",
"This room is a continuation of another conversation.": "This room is a continuation of another conversation.",
"Can't find the old version of this room (room id: %(roomId)s).": "Can't find the old version of this room (room id: %(roomId)s).",
"Click here to see older messages.": "Click here to see older messages.",
"Add an Integration": "Add an Integration",
"You are about to be taken to a third-party site so you can authenticate your account for use with %(integrationsUrl)s. Do you wish to continue?": "You are about to be taken to a third-party site so you can authenticate your account for use with %(integrationsUrl)s. Do you wish to continue?",
"Edited at %(date)s": "Edited at %(date)s",
Expand Down
2 changes: 1 addition & 1 deletion src/utils/permalinks/Permalinks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export class RoomPermalinkCreator {
// Some of the tests done by this class are relatively expensive, so normally
// throttled to not happen on every update. Pass false as the shouldThrottle
// param to disable this behaviour, eg. for tests.
public constructor(private room: Room, roomId: string | null = null, shouldThrottle = true) {
public constructor(private room: Room | null, roomId: string | null = null, shouldThrottle = true) {
richvdh marked this conversation as resolved.
Show resolved Hide resolved
this.roomId = room ? room.roomId : roomId!;

if (!this.roomId) {
Expand Down
62 changes: 58 additions & 4 deletions test/components/views/messages/RoomPredecessorTile-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { RoomPredecessorTile } from "../../../../src/components/views/messages/R
import { stubClient, upsertRoomStateEvents } from "../../../test-utils/test-utils";
import { Action } from "../../../../src/dispatcher/actions";
import RoomContext from "../../../../src/contexts/RoomContext";
import { getRoomContext } from "../../../test-utils";
import { filterConsole, getRoomContext } from "../../../test-utils";
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";

jest.mock("../../../../src/dispatcher/dispatcher");
Expand Down Expand Up @@ -62,6 +62,17 @@ describe("<RoomPredecessorTile />", () => {
},
event_id: "$create",
});
const viaPredecessorEvent = new MatrixEvent({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const viaPredecessorEvent = new MatrixEvent({
// a predecessor event that has a `via_servers` property
const viaPredecessorEvent = new MatrixEvent({

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hopefully made self-documenting (!) by 849b45b

type: EventType.RoomPredecessor,
state_key: "",
sender: userId,
room_id: roomId,
content: {
predecessor_room_id: "old_room_id_from_predecessor",
via_servers: ["a.example.com", "b.example.com"],
},
event_id: "$create",
});
const predecessorEventWithEventId = new MatrixEvent({
type: EventType.RoomPredecessor,
state_key: "",
Expand All @@ -83,6 +94,8 @@ describe("<RoomPredecessorTile />", () => {
upsertRoomStateEvents(roomCreateAndPredecessorWithEventId, [createEvent, predecessorEventWithEventId]);
const roomNoPredecessors = new Room(roomId, client, userId);
upsertRoomStateEvents(roomNoPredecessors, [createEventWithoutPredecessor]);
const roomCreateAndViaPredecessor = new Room(roomId, client, userId);
upsertRoomStateEvents(roomCreateAndViaPredecessor, [createEvent, viaPredecessorEvent]);

beforeEach(() => {
jest.clearAllMocks();
Expand Down Expand Up @@ -118,9 +131,14 @@ describe("<RoomPredecessorTile />", () => {
);
});

it("Shows an empty div if there is no predecessor", () => {
renderTile(roomNoPredecessors);
expect(screen.queryByText("Click here to see older messages.", { exact: false })).toBeNull();
describe("(filtering warnings about no predecessor)", () => {
filterConsole("RoomPredecessorTile unexpectedly used in a room with no predecessor.");

it("Shows an empty div if there is no predecessor", () => {
filterConsole;
andybalaam marked this conversation as resolved.
Show resolved Hide resolved
renderTile(roomNoPredecessors);
expect(screen.queryByText("Click here to see older messages.", { exact: false })).toBeNull();
});
});

it("Opens the old room on click", async () => {
Expand Down Expand Up @@ -149,6 +167,19 @@ describe("<RoomPredecessorTile />", () => {
);
});

describe("If the predecessor room is not found", () => {
filterConsole("Failed to find predecessor room with id old_room_id");

beforeEach(() => {
mocked(MatrixClientPeg.get().getRoom).mockReturnValue(null);
});

it("Shows an error if there are no via servers", () => {
renderTile(roomCreateAndPredecessor);
expect(screen.getByText("Can't find the old version of this room", { exact: false })).toBeInTheDocument();
});
});

describe("When feature_dynamic_room_predecessors = true", () => {
beforeEach(() => {
jest.spyOn(SettingsStore, "getValue").mockImplementation(
Expand Down Expand Up @@ -183,5 +214,28 @@ describe("<RoomPredecessorTile />", () => {
"https://matrix.to/#/old_room_id_from_predecessor/tombstone_event_id_from_predecessor",
);
});

describe("If the predecessor room is not found", () => {
filterConsole("Failed to find predecessor room with id old_room_id");

beforeEach(() => {
mocked(MatrixClientPeg.get().getRoom).mockReturnValue(null);
});

it("Shows an error if there are no via servers", () => {
renderTile(roomCreateAndPredecessor);
expect(
screen.getByText("Can't find the old version of this room", { exact: false }),
).toBeInTheDocument();
});

it("Shows a tile if there are via servers", () => {
renderTile(roomCreateAndViaPredecessor);
expect(screen.getByText("Click here to see older messages.")).toHaveAttribute(
"href",
"https://matrix.to/#/old_room_id_from_predecessor?via=a.example.com&via=b.example.com",
);
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ describe("AdvancedRoomSettingsTab", () => {
mocked(dis.dispatch).mockReset();
mocked(room.findPredecessor).mockImplementation((msc3946: boolean) =>
msc3946
? { roomId: "old_room_id_via_predecessor" }
? { roomId: "old_room_id_via_predecessor", viaServers: ["one.example.com", "two.example.com"] }
: { roomId: "old_room_id", eventId: "tombstone_event_id" },
);
});
Expand Down Expand Up @@ -138,6 +138,7 @@ describe("AdvancedRoomSettingsTab", () => {
action: Action.ViewRoom,
event_id: undefined,
room_id: "old_room_id_via_predecessor",
via_servers: ["one.example.com", "two.example.com"],
metricsTrigger: "WebPredecessorSettings",
metricsViaKeyboard: false,
});
Expand Down
16 changes: 16 additions & 0 deletions test/utils/permalinks/MatrixToPermalinkConstructor-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,20 @@ describe("MatrixToPermalinkConstructor", () => {
);
});
});

describe("forRoom", () => {
it("constructs a link given a room ID and via servers", () => {
expect(peramlinkConstructor.forRoom("!myroom:example.com", ["one.example.com", "two.example.com"])).toEqual(
"https://matrix.to/#/!myroom:example.com?via=one.example.com&via=two.example.com",
);
});
});

describe("forEvent", () => {
it("constructs a link given an event ID, room ID and via servers", () => {
expect(
peramlinkConstructor.forEvent("!myroom:example.com", "$event4", ["one.example.com", "two.example.com"]),
).toEqual("https://matrix.to/#/!myroom:example.com/$event4?via=one.example.com&via=two.example.com");
});
});
});