Skip to content

Commit ebef0d3

Browse files
Implement new memberlist design with MVVM architecture (#28874)
* Add new e2e icon for the member tile * Add new presence icon for member tile * Implement new member tile * Implement memberlist view model * Implement new memberlist header view * Support the new memberlist in Diasambiguated profile 1. Use MemberInfo instead of RoomMember 2. CSS changes to reflect the new design * Implement new memberlist view * Add and use a new overflow component We used the EntityTile component as a pretend overflow tile in some places. This new lighter component is added so that we can remove the complex EntityTile component. * Remove old code * Add/remove css files from _components.pcss * Increase minimum width as per design * Actually use the new memberlist view * Fix broken jest tests * Add jest tests * Playwright: Make it possible to disable presence * Add playwright tests * Fix lint error * Undo translation changes that must be done via localazy * Update license header * Use waitFor instead of setTimeout * Remove comment * Switch over from template to container hs * Revert unintended change * Move config to top level
1 parent f1899b9 commit ebef0d3

File tree

57 files changed

+2456
-1788
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+2456
-1788
lines changed

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@
9090
"@matrix-org/spec": "^1.7.0",
9191
"@sentry/browser": "^8.0.0",
9292
"@types/png-chunks-extract": "^1.0.2",
93-
"@vector-im/compound-design-tokens": "^2.0.1",
93+
"@vector-im/compound-design-tokens": "^2.1.0",
9494
"@vector-im/compound-web": "^7.5.0",
9595
"@vector-im/matrix-wysiwyg": "2.38.0",
9696
"@zxcvbn-ts/core": "^3.0.4",
@@ -151,7 +151,9 @@
151151
"temporal-polyfill": "^0.2.5",
152152
"ua-parser-js": "^1.0.2",
153153
"uuid": "^11.0.0",
154-
"what-input": "^5.2.10"
154+
"what-input": "^5.2.10",
155+
"@types/react-virtualized": "^9.21.30",
156+
"react-virtualized": "^9.22.5"
155157
},
156158
"devDependencies": {
157159
"@action-validator/cli": "^0.6.0",

playwright/e2e/crypto/dehydration.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const ROOM_NAME = "Test room";
1616
const NAME = "Alice";
1717

1818
function getMemberTileByName(page: Page, name: string): Locator {
19-
return page.locator(`.mx_EntityTile, [title="${name}"]`);
19+
return page.locator(`.mx_MemberTileView, [title="${name}"]`);
2020
}
2121

2222
test.use({
@@ -88,7 +88,7 @@ test.describe("Dehydration", () => {
8888
await viewRoomSummaryByName(page, app, ROOM_NAME);
8989

9090
await page.locator(".mx_RightPanel").getByRole("menuitem", { name: "People" }).click();
91-
await expect(page.locator(".mx_MemberList")).toBeVisible();
91+
await expect(page.locator(".mx_MemberListView")).toBeVisible();
9292

9393
await getMemberTileByName(page, NAME).click();
9494
await page.locator(".mx_UserInfo_devices .mx_UserInfo_expand").click();

playwright/e2e/lazy-loading/lazy-loading.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ test.describe("Lazy Loading", () => {
7878
}
7979

8080
function getMemberInMemberlist(page: Page, name: string): Locator {
81-
return page.locator(".mx_MemberList .mx_EntityTile_name").filter({ hasText: name });
81+
return page.locator(".mx_MemberListView .mx_MemberTileView_name").filter({ hasText: name });
8282
}
8383

8484
async function checkMemberList(page: Page, charlies: Bot[]) {
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
Copyright 2024 New Vector Ltd.
3+
4+
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
5+
Please see LICENSE files in the repository root for full details.
6+
*/
7+
8+
import { test, expect } from "../../element-web-test";
9+
import { Bot } from "../../pages/bot";
10+
11+
const ROOM_NAME = "Test room";
12+
const NAME = "Alice";
13+
14+
test.use({
15+
synapseConfigOptions: {
16+
presence: {
17+
enabled: false,
18+
include_offline_users_on_sync: false,
19+
},
20+
},
21+
displayName: NAME,
22+
disablePresence: true,
23+
});
24+
25+
test.describe("Memberlist", () => {
26+
test.beforeEach(async ({ app, user, page, homeserver }, testInfo) => {
27+
testInfo.setTimeout(testInfo.timeout + 30_000);
28+
const id = await app.client.createRoom({ name: ROOM_NAME });
29+
const newBots: Bot[] = [];
30+
const names = ["Bob", "Bob", "Susan"];
31+
for (let i = 0; i < 3; i++) {
32+
const displayName = names[i];
33+
const autoAcceptInvites = displayName !== "Susan";
34+
const bot = new Bot(page, homeserver, { displayName, startClient: true, autoAcceptInvites });
35+
await bot.prepareClient();
36+
await app.client.inviteUser(id, bot.credentials?.userId);
37+
newBots.push(bot);
38+
}
39+
});
40+
41+
test("Renders correctly", { tag: "@screenshot" }, async ({ page, app }) => {
42+
await app.viewRoomByName(ROOM_NAME);
43+
const memberlist = await app.toggleMemberlistPanel();
44+
await expect(memberlist.locator(".mx_MemberTileView")).toHaveCount(4);
45+
await expect(memberlist.getByText("(Invited)")).toHaveCount(1);
46+
await expect(page.locator(".mx_MemberListView")).toMatchScreenshot("with-four-members.png");
47+
});
48+
});

playwright/e2e/right-panel/right-panel.spec.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const ROOM_ADDRESS_LONG =
2424
"loremIpsumDolorSitAmetConsecteturAdipisicingElitSedDoEiusmodTemporIncididuntUtLaboreEtDoloreMagnaAliqua";
2525

2626
function getMemberTileByName(page: Page, name: string): Locator {
27-
return page.locator(`.mx_EntityTile, [title="${name}"]`);
27+
return page.locator(`.mx_MemberTileView, [title="${name}"]`);
2828
}
2929

3030
test.describe("RightPanel", () => {
@@ -107,14 +107,14 @@ test.describe("RightPanel", () => {
107107
await viewRoomSummaryByName(page, app, ROOM_NAME);
108108

109109
await page.locator(".mx_RightPanel").getByRole("menuitem", { name: "People" }).click();
110-
await expect(page.locator(".mx_MemberList")).toBeVisible();
110+
await expect(page.locator(".mx_MemberListView")).toBeVisible();
111111

112112
await getMemberTileByName(page, NAME).click();
113113
await expect(page.locator(".mx_UserInfo")).toBeVisible();
114114
await expect(page.locator(".mx_UserInfo_profile").getByText(NAME)).toBeVisible();
115115

116116
await page.getByTestId("base-card-back-button").click();
117-
await expect(page.locator(".mx_MemberList")).toBeVisible();
117+
await expect(page.locator(".mx_MemberListView")).toBeVisible();
118118

119119
await page.getByLabel("Room info").nth(1).click();
120120
await checkRoomSummaryCard(page, ROOM_NAME);
@@ -130,14 +130,14 @@ test.describe("RightPanel", () => {
130130
.locator(".mx_RoomInfoLine_private")
131131
.getByRole("button", { name: /\d member/ })
132132
.click();
133-
await expect(page.locator(".mx_MemberList")).toBeVisible();
133+
await expect(page.locator(".mx_MemberListView")).toBeVisible();
134134

135135
await getMemberTileByName(page, NAME).click();
136136
await expect(page.locator(".mx_UserInfo")).toBeVisible();
137137
await expect(page.locator(".mx_UserInfo_profile").getByText(NAME)).toBeVisible();
138138

139139
await page.getByTestId("base-card-back-button").click();
140-
await expect(page.locator(".mx_MemberList")).toBeVisible();
140+
await expect(page.locator(".mx_MemberListView")).toBeVisible();
141141
});
142142
});
143143
});

playwright/element-web-test.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ export interface Fixtures {
9999
bot: Bot;
100100
labsFlags: string[];
101101
webserver: Webserver;
102+
disablePresence: boolean;
102103
}
103104

104105
export const test = base.extend<Fixtures>({
@@ -110,8 +111,9 @@ export const test = base.extend<Fixtures>({
110111
);
111112
await use(context);
112113
},
114+
disablePresence: false,
113115
config: {}, // We merge this atop the default CONFIG_JSON in the page fixture to make extending it easier
114-
page: async ({ homeserver, context, page, config, labsFlags }, use) => {
116+
page: async ({ homeserver, context, page, config, labsFlags, disablePresence }, use) => {
115117
await context.route(`http://localhost:8080/config.json*`, async (route) => {
116118
const json = {
117119
...CONFIG_JSON,
@@ -131,6 +133,11 @@ export const test = base.extend<Fixtures>({
131133
return obj;
132134
}, {}),
133135
};
136+
if (disablePresence) {
137+
json["enable_presence_by_hs_url"] = {
138+
[homeserver.baseUrl]: false,
139+
};
140+
}
134141
await route.fulfill({ json });
135142
});
136143
await use(page);

playwright/pages/ElementAppPage.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,18 @@ export class ElementAppPage {
177177
return this.page.locator(".mx_RightPanel");
178178
}
179179

180+
/**
181+
* Opens/closes the memberlist panel
182+
* @returns locator to the memberlist panel
183+
*/
184+
public async toggleMemberlistPanel(): Promise<Locator> {
185+
const locator = this.page.locator(".mx_FacePile");
186+
await locator.click();
187+
const memberlist = this.page.locator(".mx_MemberListView");
188+
await memberlist.waitFor();
189+
return memberlist;
190+
}
191+
180192
/**
181193
* Get a locator for the tooltip associated with an element
182194
* @param e The element with the tooltip
17.5 KB
Loading

playwright/testcontainers/synapse.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ const DEFAULT_CONFIG = {
132132
experimental_features: {},
133133
oidc_providers: [],
134134
serve_server_wellknown: true,
135+
presence: {
136+
enabled: true,
137+
include_offline_users_on_sync: true,
138+
},
135139
};
136140

137141
export type SynapseConfigOptions = Partial<typeof DEFAULT_CONFIG>;

res/css/_components.pcss

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,9 +278,9 @@
278278
@import "./views/rooms/_CallGuestLinkButton.pcss";
279279
@import "./views/rooms/_DecryptionFailureBar.pcss";
280280
@import "./views/rooms/_E2EIcon.pcss";
281+
@import "./views/rooms/_E2EIconView.pcss";
281282
@import "./views/rooms/_EditMessageComposer.pcss";
282283
@import "./views/rooms/_EmojiButton.pcss";
283-
@import "./views/rooms/_EntityTile.pcss";
284284
@import "./views/rooms/_EventBubbleTile.pcss";
285285
@import "./views/rooms/_EventPreview.pcss";
286286
@import "./views/rooms/_EventTile.pcss";
@@ -290,13 +290,17 @@
290290
@import "./views/rooms/_LinkPreviewGroup.pcss";
291291
@import "./views/rooms/_LinkPreviewWidget.pcss";
292292
@import "./views/rooms/_LiveContentSummary.pcss";
293-
@import "./views/rooms/_MemberList.pcss";
293+
@import "./views/rooms/_MemberListHeaderView.pcss";
294+
@import "./views/rooms/_MemberListView.pcss";
295+
@import "./views/rooms/_MemberTileView.pcss";
294296
@import "./views/rooms/_MessageComposer.pcss";
295297
@import "./views/rooms/_MessageComposerFormatBar.pcss";
296298
@import "./views/rooms/_NewRoomIntro.pcss";
297299
@import "./views/rooms/_NotificationBadge.pcss";
300+
@import "./views/rooms/_OverflowTile.pcss";
298301
@import "./views/rooms/_PinnedEventTile.pcss";
299302
@import "./views/rooms/_PinnedMessageBanner.pcss";
303+
@import "./views/rooms/_PresenceIconView.pcss";
300304
@import "./views/rooms/_PresenceLabel.pcss";
301305
@import "./views/rooms/_ReadReceiptGroup.pcss";
302306
@import "./views/rooms/_ReplyPreview.pcss";

0 commit comments

Comments
 (0)