Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement new memberlist design with MVVM architecture #28874

Merged
merged 26 commits into from
Jan 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
656d3e8
Add new e2e icon for the member tile
MidhunSureshR Jan 5, 2025
45c1bd1
Add new presence icon for member tile
MidhunSureshR Jan 5, 2025
7768795
Implement new member tile
MidhunSureshR Jan 5, 2025
4f50174
Implement memberlist view model
MidhunSureshR Jan 5, 2025
6eb51b3
Implement new memberlist header view
MidhunSureshR Jan 5, 2025
697d15a
Support the new memberlist in Diasambiguated profile
MidhunSureshR Jan 5, 2025
9eca64c
Implement new memberlist view
MidhunSureshR Jan 5, 2025
3561aec
Add and use a new overflow component
MidhunSureshR Jan 5, 2025
c27e2fb
Remove old code
MidhunSureshR Jan 5, 2025
cf0726d
Add/remove css files from _components.pcss
MidhunSureshR Jan 5, 2025
ceb8643
Increase minimum width as per design
MidhunSureshR Jan 5, 2025
e6e0360
Actually use the new memberlist view
MidhunSureshR Jan 5, 2025
41e20e5
Fix broken jest tests
MidhunSureshR Jan 5, 2025
a57d0b7
Add jest tests
MidhunSureshR Jan 5, 2025
2c4d3d5
Playwright: Make it possible to disable presence
MidhunSureshR Jan 5, 2025
0b28e20
Add playwright tests
MidhunSureshR Jan 5, 2025
ad96434
Fix lint error
MidhunSureshR Jan 5, 2025
ec78793
Undo translation changes that must be done via localazy
MidhunSureshR Jan 6, 2025
64ef538
Merge branch 'develop' into midhun/memberlist-redesign
MidhunSureshR Jan 6, 2025
9ac4da3
Update license header
MidhunSureshR Jan 6, 2025
0147e04
Use waitFor instead of setTimeout
MidhunSureshR Jan 6, 2025
80baac2
Remove comment
MidhunSureshR Jan 6, 2025
04413ed
Merge branch 'develop' into midhun/memberlist-redesign
MidhunSureshR Jan 8, 2025
9d35514
Switch over from template to container hs
MidhunSureshR Jan 8, 2025
37a6d09
Revert unintended change
MidhunSureshR Jan 8, 2025
2bf96cc
Move config to top level
MidhunSureshR Jan 8, 2025
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
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
"@matrix-org/spec": "^1.7.0",
"@sentry/browser": "^8.0.0",
"@types/png-chunks-extract": "^1.0.2",
"@vector-im/compound-design-tokens": "^2.0.1",
"@vector-im/compound-design-tokens": "^2.1.0",
"@vector-im/compound-web": "^7.5.0",
"@vector-im/matrix-wysiwyg": "2.38.0",
"@zxcvbn-ts/core": "^3.0.4",
Expand Down Expand Up @@ -151,7 +151,9 @@
"temporal-polyfill": "^0.2.5",
"ua-parser-js": "^1.0.2",
"uuid": "^11.0.0",
"what-input": "^5.2.10"
"what-input": "^5.2.10",
"@types/react-virtualized": "^9.21.30",
"react-virtualized": "^9.22.5"
},
"devDependencies": {
"@action-validator/cli": "^0.6.0",
Expand Down
4 changes: 2 additions & 2 deletions playwright/e2e/crypto/dehydration.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const ROOM_NAME = "Test room";
const NAME = "Alice";

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

test.describe("Dehydration", () => {
Expand Down Expand Up @@ -88,7 +88,7 @@ test.describe("Dehydration", () => {
await viewRoomSummaryByName(page, app, ROOM_NAME);

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

await getMemberTileByName(page, NAME).click();
await page.locator(".mx_UserInfo_devices .mx_UserInfo_expand").click();
Expand Down
2 changes: 1 addition & 1 deletion playwright/e2e/lazy-loading/lazy-loading.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ test.describe("Lazy Loading", () => {
}

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

async function checkMemberList(page: Page, charlies: Bot[]) {
Expand Down
48 changes: 48 additions & 0 deletions playwright/e2e/right-panel/memberlist.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
Copyright 2024 New Vector Ltd.

SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/

import { test, expect } from "../../element-web-test";
import { Bot } from "../../pages/bot";

const ROOM_NAME = "Test room";
const NAME = "Alice";

test.use({
synapseConfigOptions: {
presence: {
enabled: false,
include_offline_users_on_sync: false,
},
},
displayName: NAME,
disablePresence: true,
});

test.describe("Memberlist", () => {
test.beforeEach(async ({ app, user, page, homeserver }, testInfo) => {
testInfo.setTimeout(testInfo.timeout + 30_000);
const id = await app.client.createRoom({ name: ROOM_NAME });
const newBots: Bot[] = [];
const names = ["Bob", "Bob", "Susan"];
for (let i = 0; i < 3; i++) {
const displayName = names[i];
const autoAcceptInvites = displayName !== "Susan";
const bot = new Bot(page, homeserver, { displayName, startClient: true, autoAcceptInvites });
await bot.prepareClient();
await app.client.inviteUser(id, bot.credentials?.userId);
newBots.push(bot);
}
});

test("Renders correctly", { tag: "@screenshot" }, async ({ page, app }) => {
await app.viewRoomByName(ROOM_NAME);
const memberlist = await app.toggleMemberlistPanel();
await expect(memberlist.locator(".mx_MemberTileView")).toHaveCount(4);
await expect(memberlist.getByText("(Invited)")).toHaveCount(1);
await expect(page.locator(".mx_MemberListView")).toMatchScreenshot("with-four-members.png");
});
});
10 changes: 5 additions & 5 deletions playwright/e2e/right-panel/right-panel.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const ROOM_ADDRESS_LONG =
"loremIpsumDolorSitAmetConsecteturAdipisicingElitSedDoEiusmodTemporIncididuntUtLaboreEtDoloreMagnaAliqua";

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

test.describe("RightPanel", () => {
Expand Down Expand Up @@ -107,14 +107,14 @@ test.describe("RightPanel", () => {
await viewRoomSummaryByName(page, app, ROOM_NAME);

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

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

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

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

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

await page.getByTestId("base-card-back-button").click();
await expect(page.locator(".mx_MemberList")).toBeVisible();
await expect(page.locator(".mx_MemberListView")).toBeVisible();
});
});
});
9 changes: 8 additions & 1 deletion playwright/element-web-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
bot: Bot;
labsFlags: string[];
webserver: Webserver;
disablePresence: boolean;
}

export const test = base.extend<Fixtures>({
Expand All @@ -110,8 +111,9 @@
);
await use(context);
},
disablePresence: false,
config: {}, // We merge this atop the default CONFIG_JSON in the page fixture to make extending it easier
page: async ({ homeserver, context, page, config, labsFlags }, use) => {
page: async ({ homeserver, context, page, config, labsFlags, disablePresence }, use) => {
await context.route(`http://localhost:8080/config.json*`, async (route) => {
const json = {
...CONFIG_JSON,
Expand All @@ -131,6 +133,11 @@
return obj;
}, {}),
};
if (disablePresence) {
json["enable_presence_by_hs_url"] = {
[homeserver.baseUrl]: false,
};
}
await route.fulfill({ json });
});
await use(page);
Expand Down Expand Up @@ -306,12 +313,12 @@

// We add a custom style tag before taking screenshots
const style = (await page.addStyleTag({
content: css,

Check failure on line 316 in playwright/element-web-test.ts

View workflow job for this annotation

GitHub Actions / Run Tests [Chrome] 4/6

[Chrome] › share-dialog/share-dialog.spec.ts:32:9 › Share dialog › should share a room member @screenshot

2) [Chrome] › share-dialog/share-dialog.spec.ts:32:9 › Share dialog › should share a room member @screenshot Error: expect.toMatchScreenshot: Test ended. at ../element-web-test.ts:316 314 | 315 | // We add a custom style tag before taking screenshots > 316 | const style = (await page.addStyleTag({ | ^ 317 | content: css, 318 | })) as ElementHandle<Element>; 319 | at Object.toMatchScreenshot (/home/runner/work/element-web/element-web/playwright/element-web-test.ts:316:35) at /home/runner/work/element-web/element-web/playwright/e2e/share-dialog/share-dialog.spec.ts:43:24
})) as ElementHandle<Element>;

const screenshotName = sanitizeFilePathBeforeExtension(name);
await baseExpect(receiver).toHaveScreenshot(screenshotName, options);

Check failure on line 321 in playwright/element-web-test.ts

View workflow job for this annotation

GitHub Actions / Run Tests [Chrome] 4/6

[Chrome] › share-dialog/share-dialog.spec.ts:19:9 › Share dialog › should share a room @screenshot

1) [Chrome] › share-dialog/share-dialog.spec.ts:19:9 › Share dialog › should share a room @screenshot Error: expect.toHaveScreenshot(share-dialog-room.png): Test ended. Call log: - expect.toHaveScreenshot(share-dialog-room.png) with timeout 5000ms - verifying given screenshot expectation - waiting for getByRole('dialog', { name: 'Share room' }) at ../element-web-test.ts:321 319 | 320 | const screenshotName = sanitizeFilePathBeforeExtension(name); > 321 | await baseExpect(receiver).toHaveScreenshot(screenshotName, options); | ^ 322 | 323 | await style.evaluate((tag) => tag.remove()); 324 | at Object.toMatchScreenshot (/home/runner/work/element-web/element-web/playwright/element-web-test.ts:321:9)

Check failure on line 321 in playwright/element-web-test.ts

View workflow job for this annotation

GitHub Actions / Run Tests [Chrome] 4/6

[Chrome] › share-dialog/share-dialog.spec.ts:49:9 › Share dialog › should share an event @screenshot

3) [Chrome] › share-dialog/share-dialog.spec.ts:49:9 › Share dialog › should share an event @screenshot Error: expect.toHaveScreenshot(share-dialog-event.png): Test ended. Call log: - expect.toHaveScreenshot(share-dialog-event.png) with timeout 5000ms - verifying given screenshot expectation - waiting for getByRole('dialog', { name: 'Share Room Message' }) - locator resolved to <div role="dialog" class="mx_ShareDialog" data-focus-lock-disabled="false" aria-describedby="mx_Dialog_content" aria-labelledby="mx_BaseDialog_title">…</div> - taking element screenshot - disabled all CSS animations - waiting for fonts to load... - fonts loaded - attempting scroll into view action - waiting for element to be stable at ../element-web-test.ts:321 319 | 320 | const screenshotName = sanitizeFilePathBeforeExtension(name); > 321 | await baseExpect(receiver).toHaveScreenshot(screenshotName, options); | ^ 322 | 323 | await style.evaluate((tag) => tag.remove()); 324 | at Object.toMatchScreenshot (/home/runner/work/element-web/element-web/playwright/element-web-test.ts:321:9)
await style.evaluate((tag) => tag.remove());

testInfo.annotations.push({
Expand Down
12 changes: 12 additions & 0 deletions playwright/pages/ElementAppPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@
.getByRole("tree", { name: "Rooms" })
.locator(`[title="${name}"],[aria-label="${name}"]`)
.first()
.click();

Check failure on line 96 in playwright/pages/ElementAppPage.ts

View workflow job for this annotation

GitHub Actions / Run Tests [Chrome] 1/6

[Chrome] › audio-player/audio-player.spec.ts:137:9 › Audio player › should be correctly rendered - light theme @no-firefox @no-webkit @screenshot

1) [Chrome] › audio-player/audio-player.spec.ts:137:9 › Audio player › should be correctly rendered - light theme @no-firefox @no-webkit @screenshot Error: locator.click: Test timeout of 30000ms exceeded. Call log: - waiting for getByRole('tree', { name: 'Rooms' }).locator('[title="Test Room"],[aria-label="Test Room"]').first() at ../pages/ElementAppPage.ts:96 94 | .locator(`[title="${name}"],[aria-label="${name}"]`) 95 | .first() > 96 | .click(); | ^ 97 | } 98 | 99 | public async viewRoomById(roomId: string): Promise<void> { at ElementAppPage.viewRoomByName (/home/runner/work/element-web/element-web/playwright/pages/ElementAppPage.ts:96:14) at /home/runner/work/element-web/element-web/playwright/e2e/audio-player/audio-player.spec.ts:127:19
}

public async viewRoomById(roomId: string): Promise<void> {
Expand Down Expand Up @@ -177,6 +177,18 @@
return this.page.locator(".mx_RightPanel");
}

/**
* Opens/closes the memberlist panel
* @returns locator to the memberlist panel
*/
public async toggleMemberlistPanel(): Promise<Locator> {
const locator = this.page.locator(".mx_FacePile");
await locator.click();
const memberlist = this.page.locator(".mx_MemberListView");
await memberlist.waitFor();
return memberlist;
}

/**
* Get a locator for the tooltip associated with an element
* @param e The element with the tooltip
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions playwright/testcontainers/synapse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ const DEFAULT_CONFIG = {
experimental_features: {},
oidc_providers: [],
serve_server_wellknown: true,
presence: {
enabled: true,
include_offline_users_on_sync: true,
},
};

export type SynapseConfigOptions = Partial<typeof DEFAULT_CONFIG>;
Expand Down
8 changes: 6 additions & 2 deletions res/css/_components.pcss
Original file line number Diff line number Diff line change
Expand Up @@ -278,9 +278,9 @@
@import "./views/rooms/_CallGuestLinkButton.pcss";
@import "./views/rooms/_DecryptionFailureBar.pcss";
@import "./views/rooms/_E2EIcon.pcss";
@import "./views/rooms/_E2EIconView.pcss";
@import "./views/rooms/_EditMessageComposer.pcss";
@import "./views/rooms/_EmojiButton.pcss";
@import "./views/rooms/_EntityTile.pcss";
@import "./views/rooms/_EventBubbleTile.pcss";
@import "./views/rooms/_EventPreview.pcss";
@import "./views/rooms/_EventTile.pcss";
Expand All @@ -290,13 +290,17 @@
@import "./views/rooms/_LinkPreviewGroup.pcss";
@import "./views/rooms/_LinkPreviewWidget.pcss";
@import "./views/rooms/_LiveContentSummary.pcss";
@import "./views/rooms/_MemberList.pcss";
@import "./views/rooms/_MemberListHeaderView.pcss";
@import "./views/rooms/_MemberListView.pcss";
@import "./views/rooms/_MemberTileView.pcss";
@import "./views/rooms/_MessageComposer.pcss";
@import "./views/rooms/_MessageComposerFormatBar.pcss";
@import "./views/rooms/_NewRoomIntro.pcss";
@import "./views/rooms/_NotificationBadge.pcss";
@import "./views/rooms/_OverflowTile.pcss";
@import "./views/rooms/_PinnedEventTile.pcss";
@import "./views/rooms/_PinnedMessageBanner.pcss";
@import "./views/rooms/_PresenceIconView.pcss";
@import "./views/rooms/_PresenceLabel.pcss";
@import "./views/rooms/_ReadReceiptGroup.pcss";
@import "./views/rooms/_ReplyPreview.pcss";
Expand Down
23 changes: 22 additions & 1 deletion res/css/views/messages/_DisambiguatedProfile.pcss
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,29 @@ Please see LICENSE files in the repository root for full details.
}

.mx_DisambiguatedProfile_mxid {
margin-inline-start: 5px;
color: $secondary-content;
font-size: var(--cpd-font-size-body-sm);
margin-inline-start: 5px;
}
}

/** Disambiguated profile needs to have a different layout in the member tile */
.mx_MemberTileView .mx_DisambiguatedProfile {
display: flex;
flex-direction: column;

.mx_DisambiguatedProfile_mxid {
margin-inline-start: 0;
font: var(--cpd-font-body-sm-regular);
}

span:not(.mx_DisambiguatedProfile_mxid) {
/**
In a member tile, this span element is a flex child and so
we need the following for text overflow to work.
**/
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
20 changes: 20 additions & 0 deletions res/css/views/rooms/_E2EIconView.pcss
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
Copyright 2024 New Vector Ltd.

SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/

.mx_E2EIconView {
display: flex;
justify-content: center;
align-items: center;
}

.mx_E2EIconView_warning {
color: var(--cpd-color-icon-critical-primary);
}

.mx_E2EIconView_verified {
color: var(--cpd-color-icon-success-primary);
}
Loading
Loading