Migrate RoomView to support MSC3946 (#10088)

This commit is contained in:
Michael Weimann 2023-02-10 08:40:38 +01:00 committed by GitHub
parent 072003d9fd
commit 671fdc8665
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 52 additions and 5 deletions

View file

@ -223,6 +223,7 @@ export interface IRoomState {
narrow: boolean; narrow: boolean;
// List of undecryptable events currently visible on-screen // List of undecryptable events currently visible on-screen
visibleDecryptionFailures?: MatrixEvent[]; visibleDecryptionFailures?: MatrixEvent[];
msc3946ProcessDynamicPredecessor: boolean;
} }
interface LocalRoomViewProps { interface LocalRoomViewProps {
@ -416,6 +417,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
liveTimeline: undefined, liveTimeline: undefined,
narrow: false, narrow: false,
visibleDecryptionFailures: [], visibleDecryptionFailures: [],
msc3946ProcessDynamicPredecessor: SettingsStore.getValue("feature_dynamic_room_predecessors"),
}; };
this.dispatcherRef = dis.register(this.onAction); this.dispatcherRef = dis.register(this.onAction);
@ -467,6 +469,9 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
), ),
SettingsStore.watchSetting("urlPreviewsEnabled", null, this.onUrlPreviewsEnabledChange), SettingsStore.watchSetting("urlPreviewsEnabled", null, this.onUrlPreviewsEnabledChange),
SettingsStore.watchSetting("urlPreviewsEnabled_e2ee", null, this.onUrlPreviewsEnabledChange), SettingsStore.watchSetting("urlPreviewsEnabled_e2ee", null, this.onUrlPreviewsEnabledChange),
SettingsStore.watchSetting("feature_dynamic_room_predecessors", null, (...[, , , value]) =>
this.setState({ msc3946ProcessDynamicPredecessor: value as boolean }),
),
]; ];
} }
@ -1798,10 +1803,8 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
}; };
private getOldRoom(): Room | null { private getOldRoom(): Room | null {
const createEvent = this.state.room.currentState.getStateEvents(EventType.RoomCreate, ""); const { roomId } = this.state.room?.findPredecessor(this.state.msc3946ProcessDynamicPredecessor) || {};
if (!createEvent || !createEvent.getContent()["predecessor"]) return null; return this.context.client?.getRoom(roomId) || null;
return this.context.client.getRoom(createEvent.getContent()["predecessor"]["room_id"]);
} }
public getHiddenHighlightCount(): number { public getHiddenHighlightCount(): number {

View file

@ -65,6 +65,7 @@ const RoomContext = createContext<IRoomState>({
liveTimeline: undefined, liveTimeline: undefined,
narrow: false, narrow: false,
activeCall: null, activeCall: null,
msc3946ProcessDynamicPredecessor: false,
}); });
RoomContext.displayName = "RoomContext"; RoomContext.displayName = "RoomContext";
export default RoomContext; export default RoomContext;

View file

@ -55,6 +55,7 @@ const RoomView = wrapInMatrixClientContext(_RoomView);
describe("RoomView", () => { describe("RoomView", () => {
let cli: MockedObject<MatrixClient>; let cli: MockedObject<MatrixClient>;
let room: Room; let room: Room;
let rooms: Map<string, Room>;
let roomCount = 0; let roomCount = 0;
let stores: SdkContextClass; let stores: SdkContextClass;
@ -64,8 +65,11 @@ describe("RoomView", () => {
cli = mocked(MatrixClientPeg.get()); cli = mocked(MatrixClientPeg.get());
room = new Room(`!${roomCount++}:example.org`, cli, "@alice:example.org"); room = new Room(`!${roomCount++}:example.org`, cli, "@alice:example.org");
jest.spyOn(room, "findPredecessor");
room.getPendingEvents = () => []; room.getPendingEvents = () => [];
cli.getRoom.mockImplementation(() => room); rooms = new Map();
rooms.set(room.roomId, room);
cli.getRoom.mockImplementation((roomId: string | undefined) => rooms.get(roomId || "") || null);
// Re-emit certain events on the mocked client // Re-emit certain events on the mocked client
room.on(RoomEvent.Timeline, (...args) => cli.emit(RoomEvent.Timeline, ...args)); room.on(RoomEvent.Timeline, (...args) => cli.emit(RoomEvent.Timeline, ...args));
room.on(RoomEvent.TimelineReset, (...args) => cli.emit(RoomEvent.TimelineReset, ...args)); room.on(RoomEvent.TimelineReset, (...args) => cli.emit(RoomEvent.TimelineReset, ...args));
@ -158,6 +162,42 @@ describe("RoomView", () => {
const getRoomViewInstance = async (): Promise<_RoomView> => const getRoomViewInstance = async (): Promise<_RoomView> =>
(await mountRoomView()).find(_RoomView).instance() as _RoomView; (await mountRoomView()).find(_RoomView).instance() as _RoomView;
it("when there is no room predecessor, getHiddenHighlightCount should return 0", async () => {
const instance = await getRoomViewInstance();
expect(instance.getHiddenHighlightCount()).toBe(0);
});
describe("when there is an old room", () => {
let instance: _RoomView;
let oldRoom: Room;
beforeEach(async () => {
instance = await getRoomViewInstance();
oldRoom = new Room("!old:example.com", cli, cli.getSafeUserId());
rooms.set(oldRoom.roomId, oldRoom);
jest.spyOn(room, "findPredecessor").mockReturnValue({ roomId: oldRoom.roomId, eventId: null });
});
it("and it has 0 unreads, getHiddenHighlightCount should return 0", async () => {
jest.spyOn(oldRoom, "getUnreadNotificationCount").mockReturnValue(0);
expect(instance.getHiddenHighlightCount()).toBe(0);
// assert that msc3946ProcessDynamicPredecessor is false by default
expect(room.findPredecessor).toHaveBeenCalledWith(false);
});
it("and it has 23 unreads, getHiddenHighlightCount should return 23", async () => {
jest.spyOn(oldRoom, "getUnreadNotificationCount").mockReturnValue(23);
expect(instance.getHiddenHighlightCount()).toBe(23);
});
it("and feature_dynamic_room_predecessors is enabled it should pass the setting to findPredecessor", async () => {
SettingsStore.setValue("feature_dynamic_room_predecessors", null, SettingLevel.DEVICE, true);
expect(instance.getHiddenHighlightCount()).toBe(0);
expect(room.findPredecessor).toHaveBeenCalledWith(true);
SettingsStore.setValue("feature_dynamic_room_predecessors", null, SettingLevel.DEVICE, null);
});
});
it("updates url preview visibility on encryption state change", async () => { it("updates url preview visibility on encryption state change", async () => {
// we should be starting unencrypted // we should be starting unencrypted
expect(cli.isCryptoEnabled()).toEqual(false); expect(cli.isCryptoEnabled()).toEqual(false);
@ -248,6 +288,7 @@ describe("RoomView", () => {
beforeEach(async () => { beforeEach(async () => {
localRoom = room = await createDmLocalRoom(cli, [new DirectoryMember({ user_id: "@user:example.com" })]); localRoom = room = await createDmLocalRoom(cli, [new DirectoryMember({ user_id: "@user:example.com" })]);
rooms.set(localRoom.roomId, localRoom);
cli.store.storeRoom(room); cli.store.storeRoom(room);
}); });

View file

@ -78,6 +78,7 @@ describe("<SendMessageComposer/>", () => {
resizing: false, resizing: false,
narrow: false, narrow: false,
activeCall: null, activeCall: null,
msc3946ProcessDynamicPredecessor: false,
}; };
describe("createMessageContent", () => { describe("createMessageContent", () => {
const permalinkCreator = jest.fn() as any; const permalinkCreator = jest.fn() as any;

View file

@ -86,6 +86,7 @@ export function getRoomContext(room: Room, override: Partial<IRoomState>): IRoom
resizing: false, resizing: false,
narrow: false, narrow: false,
activeCall: null, activeCall: null,
msc3946ProcessDynamicPredecessor: false,
...override, ...override,
}; };