Gitter sunsetting: Use findPredecessor in EventTileFactory (#10075)
This commit is contained in:
parent
9743852380
commit
f1a08cd572
4 changed files with 153 additions and 9 deletions
|
@ -250,7 +250,7 @@ describe("Timeline", () => {
|
||||||
cy.contains(".mx_RoomView_body .mx_EventTile[data-scroll-tokens]", "MessageEdit").should("exist");
|
cy.contains(".mx_RoomView_body .mx_EventTile[data-scroll-tokens]", "MessageEdit").should("exist");
|
||||||
|
|
||||||
// Click top left of the event toggle, which should not be covered by MessageActionBar's safe area
|
// Click top left of the event toggle, which should not be covered by MessageActionBar's safe area
|
||||||
cy.get(".mx_EventTile .mx_ViewSourceEvent")
|
cy.get(".mx_EventTile:not(:first-child) .mx_ViewSourceEvent")
|
||||||
.should("exist")
|
.should("exist")
|
||||||
.realHover()
|
.realHover()
|
||||||
.within(() => {
|
.within(() => {
|
||||||
|
|
|
@ -22,6 +22,7 @@ import { M_POLL_START } from "matrix-js-sdk/src/@types/polls";
|
||||||
import { MatrixClient } from "matrix-js-sdk/src/client";
|
import { MatrixClient } from "matrix-js-sdk/src/client";
|
||||||
import { GroupCallIntent } from "matrix-js-sdk/src/webrtc/groupCall";
|
import { GroupCallIntent } from "matrix-js-sdk/src/webrtc/groupCall";
|
||||||
|
|
||||||
|
import SettingsStore from "../settings/SettingsStore";
|
||||||
import EditorStateTransfer from "../utils/EditorStateTransfer";
|
import EditorStateTransfer from "../utils/EditorStateTransfer";
|
||||||
import { RoomPermalinkCreator } from "../utils/permalinks/Permalinks";
|
import { RoomPermalinkCreator } from "../utils/permalinks/Permalinks";
|
||||||
import LegacyCallEventGrouper from "../components/structures/LegacyCallEventGrouper";
|
import LegacyCallEventGrouper from "../components/structures/LegacyCallEventGrouper";
|
||||||
|
@ -91,6 +92,7 @@ const HiddenEventFactory: Factory = (ref, props) => <HiddenBody ref={ref} {...pr
|
||||||
// These factories are exported for reference comparison against pickFactory()
|
// These factories are exported for reference comparison against pickFactory()
|
||||||
export const JitsiEventFactory: Factory = (ref, props) => <MJitsiWidgetEvent ref={ref} {...props} />;
|
export const JitsiEventFactory: Factory = (ref, props) => <MJitsiWidgetEvent ref={ref} {...props} />;
|
||||||
export const JSONEventFactory: Factory = (ref, props) => <ViewSourceEvent ref={ref} {...props} />;
|
export const JSONEventFactory: Factory = (ref, props) => <ViewSourceEvent ref={ref} {...props} />;
|
||||||
|
export const RoomCreateEventFactory: Factory = (ref, props) => <RoomCreate {...props} />;
|
||||||
|
|
||||||
const EVENT_TILE_TYPES = new Map<string, Factory>([
|
const EVENT_TILE_TYPES = new Map<string, Factory>([
|
||||||
[EventType.RoomMessage, MessageEventFactory], // note that verification requests are handled in pickFactory()
|
[EventType.RoomMessage, MessageEventFactory], // note that verification requests are handled in pickFactory()
|
||||||
|
@ -105,7 +107,7 @@ const EVENT_TILE_TYPES = new Map<string, Factory>([
|
||||||
const STATE_EVENT_TILE_TYPES = new Map<string, Factory>([
|
const STATE_EVENT_TILE_TYPES = new Map<string, Factory>([
|
||||||
[EventType.RoomEncryption, (ref, props) => <EncryptionEvent ref={ref} {...props} />],
|
[EventType.RoomEncryption, (ref, props) => <EncryptionEvent ref={ref} {...props} />],
|
||||||
[EventType.RoomCanonicalAlias, TextualEventFactory],
|
[EventType.RoomCanonicalAlias, TextualEventFactory],
|
||||||
[EventType.RoomCreate, (_ref, props) => <RoomCreate {...props} />],
|
[EventType.RoomCreate, RoomCreateEventFactory],
|
||||||
[EventType.RoomMember, TextualEventFactory],
|
[EventType.RoomMember, TextualEventFactory],
|
||||||
[EventType.RoomName, TextualEventFactory],
|
[EventType.RoomName, TextualEventFactory],
|
||||||
[EventType.RoomAvatar, (ref, props) => <RoomAvatarEvent ref={ref} {...props} />],
|
[EventType.RoomAvatar, (ref, props) => <RoomAvatarEvent ref={ref} {...props} />],
|
||||||
|
@ -213,6 +215,14 @@ export function pickFactory(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (evType === EventType.RoomCreate) {
|
||||||
|
const dynamicPredecessorsEnabled = SettingsStore.getValue("feature_dynamic_room_predecessors");
|
||||||
|
const predecessor = cli.getRoom(mxEvent.getRoomId())?.findPredecessor(dynamicPredecessorsEnabled);
|
||||||
|
if (!predecessor) {
|
||||||
|
return noEventFactoryFactory();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Enable support for m.widget event type (https://github.com/vector-im/element-web/issues/13111)
|
// TODO: Enable support for m.widget event type (https://github.com/vector-im/element-web/issues/13111)
|
||||||
if (evType === "im.vector.modular.widgets") {
|
if (evType === "im.vector.modular.widgets") {
|
||||||
let type = mxEvent.getContent()["type"];
|
let type = mxEvent.getContent()["type"];
|
||||||
|
@ -415,12 +425,15 @@ export function haveRendererForEvent(mxEvent: MatrixEvent, showHiddenEvents: boo
|
||||||
// No tile for replacement events since they update the original tile
|
// No tile for replacement events since they update the original tile
|
||||||
if (mxEvent.isRelation(RelationType.Replace)) return false;
|
if (mxEvent.isRelation(RelationType.Replace)) return false;
|
||||||
|
|
||||||
const handler = pickFactory(mxEvent, MatrixClientPeg.get(), showHiddenEvents);
|
const cli = MatrixClientPeg.get();
|
||||||
|
const handler = pickFactory(mxEvent, cli, showHiddenEvents);
|
||||||
if (!handler) return false;
|
if (!handler) return false;
|
||||||
if (handler === TextualEventFactory) {
|
if (handler === TextualEventFactory) {
|
||||||
return hasText(mxEvent, showHiddenEvents);
|
return hasText(mxEvent, showHiddenEvents);
|
||||||
} else if (handler === STATE_EVENT_TILE_TYPES.get(EventType.RoomCreate)) {
|
} else if (handler === STATE_EVENT_TILE_TYPES.get(EventType.RoomCreate)) {
|
||||||
return Boolean(mxEvent.getContent()["predecessor"]);
|
const dynamicPredecessorsEnabled = SettingsStore.getValue("feature_dynamic_room_predecessors");
|
||||||
|
const predecessor = cli.getRoom(mxEvent.getRoomId())?.findPredecessor(dynamicPredecessorsEnabled);
|
||||||
|
return Boolean(predecessor);
|
||||||
} else if (
|
} else if (
|
||||||
ElementCall.CALL_EVENT_TYPE.names.some((eventType) => handler === STATE_EVENT_TILE_TYPES.get(eventType))
|
ElementCall.CALL_EVENT_TYPE.names.some((eventType) => handler === STATE_EVENT_TILE_TYPES.get(eventType))
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -37,6 +37,7 @@ import {
|
||||||
} from "../../test-utils";
|
} from "../../test-utils";
|
||||||
import ResizeNotifier from "../../../src/utils/ResizeNotifier";
|
import ResizeNotifier from "../../../src/utils/ResizeNotifier";
|
||||||
import { IRoomState } from "../../../src/components/structures/RoomView";
|
import { IRoomState } from "../../../src/components/structures/RoomView";
|
||||||
|
import { MatrixClientPeg } from "../../../src/MatrixClientPeg";
|
||||||
|
|
||||||
jest.mock("../../../src/utils/beacon", () => ({
|
jest.mock("../../../src/utils/beacon", () => ({
|
||||||
useBeacon: jest.fn(),
|
useBeacon: jest.fn(),
|
||||||
|
@ -58,6 +59,7 @@ describe("MessagePanel", function () {
|
||||||
getRoom: jest.fn(),
|
getRoom: jest.fn(),
|
||||||
getClientWellKnown: jest.fn().mockReturnValue({}),
|
getClientWellKnown: jest.fn().mockReturnValue({}),
|
||||||
});
|
});
|
||||||
|
jest.spyOn(MatrixClientPeg, "get").mockReturnValue(client);
|
||||||
|
|
||||||
const room = new Room(roomId, client, userId);
|
const room = new Room(roomId, client, userId);
|
||||||
|
|
||||||
|
@ -464,11 +466,12 @@ describe("MessagePanel", function () {
|
||||||
|
|
||||||
it("should collapse creation events", function () {
|
it("should collapse creation events", function () {
|
||||||
const events = mkCreationEvents();
|
const events = mkCreationEvents();
|
||||||
TestUtilsMatrix.upsertRoomStateEvents(room, events);
|
|
||||||
const { container } = render(getComponent({ events }));
|
|
||||||
|
|
||||||
const createEvent = events.find((event) => event.getType() === "m.room.create");
|
const createEvent = events.find((event) => event.getType() === "m.room.create");
|
||||||
const encryptionEvent = events.find((event) => event.getType() === "m.room.encryption");
|
const encryptionEvent = events.find((event) => event.getType() === "m.room.encryption");
|
||||||
|
client.getRoom.mockImplementation((id) => (id === createEvent!.getRoomId() ? room : null));
|
||||||
|
TestUtilsMatrix.upsertRoomStateEvents(room, events);
|
||||||
|
|
||||||
|
const { container } = render(getComponent({ events }));
|
||||||
|
|
||||||
// we expect that
|
// we expect that
|
||||||
// - the room creation event, the room encryption event, and Alice inviting Bob,
|
// - the room creation event, the room encryption event, and Alice inviting Bob,
|
||||||
|
@ -508,6 +511,8 @@ describe("MessagePanel", function () {
|
||||||
|
|
||||||
it("should hide read-marker at the end of creation event summary", function () {
|
it("should hide read-marker at the end of creation event summary", function () {
|
||||||
const events = mkCreationEvents();
|
const events = mkCreationEvents();
|
||||||
|
const createEvent = events.find((event) => event.getType() === "m.room.create");
|
||||||
|
client.getRoom.mockImplementation((id) => (id === createEvent!.getRoomId() ? room : null));
|
||||||
TestUtilsMatrix.upsertRoomStateEvents(room, events);
|
TestUtilsMatrix.upsertRoomStateEvents(room, events);
|
||||||
|
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
|
|
|
@ -18,8 +18,10 @@ import {
|
||||||
JSONEventFactory,
|
JSONEventFactory,
|
||||||
MessageEventFactory,
|
MessageEventFactory,
|
||||||
pickFactory,
|
pickFactory,
|
||||||
|
RoomCreateEventFactory,
|
||||||
TextualEventFactory,
|
TextualEventFactory,
|
||||||
} from "../../src/events/EventTileFactory";
|
} from "../../src/events/EventTileFactory";
|
||||||
|
import SettingsStore from "../../src/settings/SettingsStore";
|
||||||
import { VoiceBroadcastChunkEventType, VoiceBroadcastInfoState } from "../../src/voice-broadcast";
|
import { VoiceBroadcastChunkEventType, VoiceBroadcastInfoState } from "../../src/voice-broadcast";
|
||||||
import { createTestClient, mkEvent } from "../test-utils";
|
import { createTestClient, mkEvent } from "../test-utils";
|
||||||
import { mkVoiceBroadcastInfoStateEvent } from "../voice-broadcast/utils/test-utils";
|
import { mkVoiceBroadcastInfoStateEvent } from "../voice-broadcast/utils/test-utils";
|
||||||
|
@ -27,23 +29,64 @@ import { mkVoiceBroadcastInfoStateEvent } from "../voice-broadcast/utils/test-ut
|
||||||
const roomId = "!room:example.com";
|
const roomId = "!room:example.com";
|
||||||
|
|
||||||
describe("pickFactory", () => {
|
describe("pickFactory", () => {
|
||||||
|
let client: MatrixClient;
|
||||||
|
let room: Room;
|
||||||
|
|
||||||
|
let createEventWithPredecessor: MatrixEvent;
|
||||||
|
let createEventWithoutPredecessor: MatrixEvent;
|
||||||
|
let dynamicPredecessorEvent: MatrixEvent;
|
||||||
|
|
||||||
let voiceBroadcastStartedEvent: MatrixEvent;
|
let voiceBroadcastStartedEvent: MatrixEvent;
|
||||||
let voiceBroadcastStoppedEvent: MatrixEvent;
|
let voiceBroadcastStoppedEvent: MatrixEvent;
|
||||||
let voiceBroadcastChunkEvent: MatrixEvent;
|
let voiceBroadcastChunkEvent: MatrixEvent;
|
||||||
let utdEvent: MatrixEvent;
|
let utdEvent: MatrixEvent;
|
||||||
let utdBroadcastChunkEvent: MatrixEvent;
|
let utdBroadcastChunkEvent: MatrixEvent;
|
||||||
let audioMessageEvent: MatrixEvent;
|
let audioMessageEvent: MatrixEvent;
|
||||||
let client: MatrixClient;
|
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
client = createTestClient();
|
client = createTestClient();
|
||||||
|
|
||||||
const room = new Room(roomId, client, client.getSafeUserId());
|
room = new Room(roomId, client, client.getSafeUserId());
|
||||||
mocked(client.getRoom).mockImplementation((getRoomId: string): Room | null => {
|
mocked(client.getRoom).mockImplementation((getRoomId: string): Room | null => {
|
||||||
if (getRoomId === room.roomId) return room;
|
if (getRoomId === room.roomId) return room;
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
createEventWithoutPredecessor = mkEvent({
|
||||||
|
event: true,
|
||||||
|
type: EventType.RoomCreate,
|
||||||
|
user: client.getUserId()!,
|
||||||
|
room: roomId,
|
||||||
|
content: {
|
||||||
|
creator: client.getUserId()!,
|
||||||
|
room_version: "9",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
createEventWithPredecessor = mkEvent({
|
||||||
|
event: true,
|
||||||
|
type: EventType.RoomCreate,
|
||||||
|
user: client.getUserId()!,
|
||||||
|
room: roomId,
|
||||||
|
content: {
|
||||||
|
creator: client.getUserId()!,
|
||||||
|
room_version: "9",
|
||||||
|
predecessor: {
|
||||||
|
room_id: "roomid1",
|
||||||
|
event_id: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
dynamicPredecessorEvent = mkEvent({
|
||||||
|
event: true,
|
||||||
|
type: EventType.RoomPredecessor,
|
||||||
|
user: client.getUserId()!,
|
||||||
|
room: roomId,
|
||||||
|
skey: "",
|
||||||
|
content: {
|
||||||
|
predecessor_room_id: "roomid2",
|
||||||
|
last_known_event_id: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
voiceBroadcastStartedEvent = mkVoiceBroadcastInfoStateEvent(
|
voiceBroadcastStartedEvent = mkVoiceBroadcastInfoStateEvent(
|
||||||
roomId,
|
roomId,
|
||||||
VoiceBroadcastInfoState.Started,
|
VoiceBroadcastInfoState.Started,
|
||||||
|
@ -117,6 +160,15 @@ describe("pickFactory", () => {
|
||||||
expect(pickFactory(voiceBroadcastChunkEvent, client, true)).toBe(JSONEventFactory);
|
expect(pickFactory(voiceBroadcastChunkEvent, client, true)).toBe(JSONEventFactory);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should return a JSONEventFactory for a room create event without predecessor", () => {
|
||||||
|
room.currentState.events.set(
|
||||||
|
EventType.RoomCreate,
|
||||||
|
new Map([[createEventWithoutPredecessor.getStateKey()!, createEventWithoutPredecessor]]),
|
||||||
|
);
|
||||||
|
room.currentState.events.set(EventType.RoomPredecessor, new Map());
|
||||||
|
expect(pickFactory(createEventWithoutPredecessor, client, true)).toBe(JSONEventFactory);
|
||||||
|
});
|
||||||
|
|
||||||
it("should return a TextualEventFactory for a voice broadcast stopped event", () => {
|
it("should return a TextualEventFactory for a voice broadcast stopped event", () => {
|
||||||
expect(pickFactory(voiceBroadcastStoppedEvent, client, true)).toBe(TextualEventFactory);
|
expect(pickFactory(voiceBroadcastStoppedEvent, client, true)).toBe(TextualEventFactory);
|
||||||
});
|
});
|
||||||
|
@ -131,6 +183,80 @@ describe("pickFactory", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("when not showing hidden events", () => {
|
describe("when not showing hidden events", () => {
|
||||||
|
describe("without dynamic predecessor support", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.spyOn(SettingsStore, "getValue").mockReset();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return undefined for a room without predecessor", () => {
|
||||||
|
room.currentState.events.set(
|
||||||
|
EventType.RoomCreate,
|
||||||
|
new Map([[createEventWithoutPredecessor.getStateKey()!, createEventWithoutPredecessor]]),
|
||||||
|
);
|
||||||
|
room.currentState.events.set(EventType.RoomPredecessor, new Map());
|
||||||
|
expect(pickFactory(createEventWithoutPredecessor, client, false)).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return a RoomCreateFactory for a room with fixed predecessor", () => {
|
||||||
|
room.currentState.events.set(
|
||||||
|
EventType.RoomCreate,
|
||||||
|
new Map([[createEventWithPredecessor.getStateKey()!, createEventWithPredecessor]]),
|
||||||
|
);
|
||||||
|
room.currentState.events.set(EventType.RoomPredecessor, new Map());
|
||||||
|
expect(pickFactory(createEventWithPredecessor, client, false)).toBe(RoomCreateEventFactory);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return undefined for a room with dynamic predecessor", () => {
|
||||||
|
room.currentState.events.set(
|
||||||
|
EventType.RoomCreate,
|
||||||
|
new Map([[createEventWithoutPredecessor.getStateKey()!, createEventWithoutPredecessor]]),
|
||||||
|
);
|
||||||
|
room.currentState.events.set(
|
||||||
|
EventType.RoomPredecessor,
|
||||||
|
new Map([[dynamicPredecessorEvent.getStateKey()!, dynamicPredecessorEvent]]),
|
||||||
|
);
|
||||||
|
expect(pickFactory(createEventWithoutPredecessor, client, false)).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("with dynamic predecessor support", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.spyOn(SettingsStore, "getValue")
|
||||||
|
.mockReset()
|
||||||
|
.mockImplementation((settingName) => settingName === "feature_dynamic_room_predecessors");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return undefined for a room without predecessor", () => {
|
||||||
|
room.currentState.events.set(
|
||||||
|
EventType.RoomCreate,
|
||||||
|
new Map([[createEventWithoutPredecessor.getStateKey()!, createEventWithoutPredecessor]]),
|
||||||
|
);
|
||||||
|
room.currentState.events.set(EventType.RoomPredecessor, new Map());
|
||||||
|
expect(pickFactory(createEventWithoutPredecessor, client, false)).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return a RoomCreateFactory for a room with fixed predecessor", () => {
|
||||||
|
room.currentState.events.set(
|
||||||
|
EventType.RoomCreate,
|
||||||
|
new Map([[createEventWithPredecessor.getStateKey()!, createEventWithPredecessor]]),
|
||||||
|
);
|
||||||
|
room.currentState.events.set(EventType.RoomPredecessor, new Map());
|
||||||
|
expect(pickFactory(createEventWithPredecessor, client, false)).toBe(RoomCreateEventFactory);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return a RoomCreateFactory for a room with dynamic predecessor", () => {
|
||||||
|
room.currentState.events.set(
|
||||||
|
EventType.RoomCreate,
|
||||||
|
new Map([[createEventWithoutPredecessor.getStateKey()!, createEventWithoutPredecessor]]),
|
||||||
|
);
|
||||||
|
room.currentState.events.set(
|
||||||
|
EventType.RoomPredecessor,
|
||||||
|
new Map([[dynamicPredecessorEvent.getStateKey()!, dynamicPredecessorEvent]]),
|
||||||
|
);
|
||||||
|
expect(pickFactory(createEventWithoutPredecessor, client, false)).toBe(RoomCreateEventFactory);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it("should return undefined for a voice broadcast event", () => {
|
it("should return undefined for a voice broadcast event", () => {
|
||||||
expect(pickFactory(voiceBroadcastChunkEvent, client, false)).toBeUndefined();
|
expect(pickFactory(voiceBroadcastChunkEvent, client, false)).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue