Room list: move sections out of labs to all the users (#33810)
* feat: remove section labs flag * test: update tests * feat: remove favourites and low prioriy filter in SC * test: update screenshots * test: update snapshots * test: update playwright tests * test: update playright screenshots * test: update screenshot * test: close release announcement * test: fix skeleton screenshot * test: fix sliding sync * test: update room list tests * test: update room list tests after section dnd * test: update toast screenshot * test: update again room list tests * test: update screenshot
@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
|||||||
Please see LICENSE files in the repository root for full details.
|
Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { createNewInstance, rejectToast } from "@element-hq/element-web-playwright-common";
|
import { closeReleaseAnnouncement, createNewInstance, rejectToast } from "@element-hq/element-web-playwright-common";
|
||||||
|
|
||||||
import { expect, test } from "../../element-web-test";
|
import { expect, test } from "../../element-web-test";
|
||||||
import { ElementAppPage } from "../../pages/ElementAppPage";
|
import { ElementAppPage } from "../../pages/ElementAppPage";
|
||||||
@@ -30,6 +30,11 @@ test.describe("History sharing", function () {
|
|||||||
await aliceElementApp.client.bootstrapCrossSigning(aliceCredentials);
|
await aliceElementApp.client.bootstrapCrossSigning(aliceCredentials);
|
||||||
await aliceElementApp.closeKeyStorageToast();
|
await aliceElementApp.closeKeyStorageToast();
|
||||||
|
|
||||||
|
await rejectToast(alicePage, "Notifications");
|
||||||
|
|
||||||
|
// Close the release announcement about the new room list sections
|
||||||
|
await closeReleaseAnnouncement(alicePage, "Introducing Sections");
|
||||||
|
|
||||||
// Register a second user, and open it in a second instance of the app
|
// Register a second user, and open it in a second instance of the app
|
||||||
const bobCredentials = await homeserver.registerUser(`user_${testInfo.testId}_bob`, "password", "Bob");
|
const bobCredentials = await homeserver.registerUser(`user_${testInfo.testId}_bob`, "password", "Bob");
|
||||||
const bobPage = await createNewInstance(browser, bobCredentials, {}, labsFlags);
|
const bobPage = await createNewInstance(browser, bobCredentials, {}, labsFlags);
|
||||||
@@ -37,8 +42,6 @@ test.describe("History sharing", function () {
|
|||||||
await bobElementApp.client.bootstrapCrossSigning(bobCredentials);
|
await bobElementApp.client.bootstrapCrossSigning(bobCredentials);
|
||||||
await bobElementApp.closeKeyStorageToast();
|
await bobElementApp.closeKeyStorageToast();
|
||||||
|
|
||||||
await rejectToast(aliceElementApp.page, "Notifications");
|
|
||||||
|
|
||||||
// Create the room and send a message
|
// Create the room and send a message
|
||||||
await createRoom(alicePage, "TestRoom", true);
|
await createRoom(alicePage, "TestRoom", true);
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
|||||||
Please see LICENSE files in the repository root for full details.
|
Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { closeReleaseAnnouncement } from "@element-hq/element-web-playwright-common";
|
||||||
|
|
||||||
import type { Page } from "@playwright/test";
|
import type { Page } from "@playwright/test";
|
||||||
import { test, expect } from "../../element-web-test";
|
import { test, expect } from "../../element-web-test";
|
||||||
import { openIntegrationManager } from "./utils";
|
import { openIntegrationManager } from "./utils";
|
||||||
@@ -139,6 +141,11 @@ test.describe("Integration Manager: Kick", () => {
|
|||||||
await app.viewRoomByName(ROOM_NAME);
|
await app.viewRoomByName(ROOM_NAME);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test.beforeEach(async ({ page, user, app, room }) => {
|
||||||
|
// Close the release announcement about the new room list sections
|
||||||
|
await closeReleaseAnnouncement(page, "Introducing Sections");
|
||||||
|
});
|
||||||
|
|
||||||
test("should kick the target", async ({ page, app, bot: targetUser, room }) => {
|
test("should kick the target", async ({ page, app, bot: targetUser, room }) => {
|
||||||
await app.viewRoomByName(ROOM_NAME);
|
await app.viewRoomByName(ROOM_NAME);
|
||||||
await app.client.inviteUser(room.roomId, targetUser.credentials.userId);
|
await app.client.inviteUser(room.roomId, targetUser.credentials.userId);
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
|||||||
Please see LICENSE files in the repository root for full details.
|
Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { closeReleaseAnnouncement, rejectToast } from "@element-hq/element-web-playwright-common";
|
||||||
|
|
||||||
import type { Page } from "@playwright/test";
|
import type { Page } from "@playwright/test";
|
||||||
import { test, expect } from "../../element-web-test";
|
import { test, expect } from "../../element-web-test";
|
||||||
import { openIntegrationManager } from "./utils";
|
import { openIntegrationManager } from "./utils";
|
||||||
@@ -103,6 +105,11 @@ test.describe("Integration Manager: Send Event", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test.beforeEach(async ({ page, user, app, room }) => {
|
test.beforeEach(async ({ page, user, app, room }) => {
|
||||||
|
await rejectToast(page, "Verify this device");
|
||||||
|
await rejectToast(page, "Notifications");
|
||||||
|
// Close the release announcement about the new room list sections
|
||||||
|
await closeReleaseAnnouncement(page, "Introducing Sections");
|
||||||
|
|
||||||
await app.client.setAccountData("m.widgets", {
|
await app.client.setAccountData("m.widgets", {
|
||||||
"m.integration_manager": {
|
"m.integration_manager": {
|
||||||
content: {
|
content: {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import {
|
|||||||
test.describe("Room list custom sections", () => {
|
test.describe("Room list custom sections", () => {
|
||||||
test.use({
|
test.use({
|
||||||
displayName: "Alice",
|
displayName: "Alice",
|
||||||
labsFlags: ["feature_new_room_list", "feature_room_list_sections"],
|
labsFlags: ["feature_new_room_list"],
|
||||||
botCreateOpts: {
|
botCreateOpts: {
|
||||||
displayName: "BotBob",
|
displayName: "BotBob",
|
||||||
autoAcceptInvites: true,
|
autoAcceptInvites: true,
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
import { type Visibility } from "matrix-js-sdk/src/matrix";
|
import { type Visibility } from "matrix-js-sdk/src/matrix";
|
||||||
import { type Page } from "@playwright/test";
|
import { type Page } from "@playwright/test";
|
||||||
import { rejectToast } from "@element-hq/element-web-playwright-common";
|
import { closeReleaseAnnouncement, rejectToast } from "@element-hq/element-web-playwright-common";
|
||||||
|
|
||||||
import { expect, test } from "../../../element-web-test";
|
import { expect, test } from "../../../element-web-test";
|
||||||
import { SettingLevel } from "../../../../src/settings/SettingLevel";
|
import { SettingLevel } from "../../../../src/settings/SettingLevel";
|
||||||
@@ -35,6 +35,9 @@ test.describe("Room list filters and sort", () => {
|
|||||||
// The toasts are displayed above the search section
|
// The toasts are displayed above the search section
|
||||||
await rejectToast(page, "Verify this device");
|
await rejectToast(page, "Verify this device");
|
||||||
await rejectToast(page, "Notifications");
|
await rejectToast(page, "Notifications");
|
||||||
|
|
||||||
|
// Close the release announcement about the new room list sections
|
||||||
|
await closeReleaseAnnouncement(page, "Introducing Sections");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Tombstoned rooms are not shown even when they receive updates", async ({ page, app, bot }) => {
|
test("Tombstoned rooms are not shown even when they receive updates", async ({ page, app, bot }) => {
|
||||||
@@ -177,19 +180,19 @@ test.describe("Room list filters and sort", () => {
|
|||||||
await expect.poll(() => roomList.locator("role=option").count()).toBe(2);
|
await expect.poll(() => roomList.locator("role=option").count()).toBe(2);
|
||||||
|
|
||||||
await primaryFilters.getByRole("option", { name: "Rooms" }).click();
|
await primaryFilters.getByRole("option", { name: "Rooms" }).click();
|
||||||
await expect(roomList.getByRole("option", { name: "unread room" })).toBeVisible();
|
// "Open room" prefix disambiguates the room tile from the "Toggle Chats section with
|
||||||
await expect(roomList.getByRole("option", { name: "favourite room" })).toBeVisible();
|
// unread rooms" section header button, which also matches the "unread room" substring.
|
||||||
await expect(roomList.getByRole("option", { name: "empty room" })).toBeVisible();
|
await expect(roomList.getByRole("button", { name: "Open room unread room" })).toBeVisible();
|
||||||
await expect(roomList.getByRole("option", { name: "room with mention" })).toBeVisible();
|
await expect(roomList.getByRole("button", { name: "favourite room" })).toBeVisible();
|
||||||
await expect(roomList.getByRole("option", { name: "Low prio room" })).toBeVisible();
|
await expect(roomList.getByRole("button", { name: "empty room" })).toBeVisible();
|
||||||
await expect.poll(() => roomList.locator("role=option").count()).toBe(5);
|
await expect(roomList.getByRole("button", { name: "room with mention" })).toBeVisible();
|
||||||
|
await expect(roomList.getByRole("button", { name: "Low prio room" })).toBeVisible();
|
||||||
|
// 5 room tiles spread across 3 sections (Favourites, Rooms, Low priority); each section
|
||||||
|
// header is also a button, so 5 rooms + 3 section headers = 8 buttons.
|
||||||
|
await expect.poll(() => roomList.locator("role=button").count()).toBe(8);
|
||||||
|
|
||||||
await getFilterExpandButton(page).click();
|
await getFilterExpandButton(page).click();
|
||||||
|
|
||||||
await primaryFilters.getByRole("option", { name: "Favourite" }).click();
|
|
||||||
await expect(roomList.getByRole("option", { name: "favourite room" })).toBeVisible();
|
|
||||||
await expect.poll(() => roomList.locator("role=option").count()).toBe(1);
|
|
||||||
|
|
||||||
await primaryFilters.getByRole("option", { name: "Mentions" }).click();
|
await primaryFilters.getByRole("option", { name: "Mentions" }).click();
|
||||||
await expect(roomList.getByRole("option", { name: "room with mention" })).toBeVisible();
|
await expect(roomList.getByRole("option", { name: "room with mention" })).toBeVisible();
|
||||||
await expect.poll(() => roomList.locator("role=option").count()).toBe(1);
|
await expect.poll(() => roomList.locator("role=option").count()).toBe(1);
|
||||||
@@ -216,7 +219,7 @@ test.describe("Room list filters and sort", () => {
|
|||||||
await app.settings.closeDialog();
|
await app.settings.closeDialog();
|
||||||
|
|
||||||
// Let's open a room other than unread room or unread dm
|
// Let's open a room other than unread room or unread dm
|
||||||
await roomListView.getByRole("option", { name: "Open room favourite room" }).click();
|
await roomListView.getByRole("button", { name: "Open room favourite room" }).click();
|
||||||
|
|
||||||
// Let's make the bot send a new message in both rooms
|
// Let's make the bot send a new message in both rooms
|
||||||
await bot.sendMessage(unReadDmId, "Hello!");
|
await bot.sendMessage(unReadDmId, "Hello!");
|
||||||
@@ -239,15 +242,20 @@ test.describe("Room list filters and sort", () => {
|
|||||||
await getRoomOptionsMenu(page).click();
|
await getRoomOptionsMenu(page).click();
|
||||||
await page.getByRole("menuitemradio", { name: "A-Z" }).click();
|
await page.getByRole("menuitemradio", { name: "A-Z" }).click();
|
||||||
|
|
||||||
await expect(roomListView.getByRole("option").first()).toHaveText(/empty room/);
|
// Favourite + chat section headers are buttons + favourite room
|
||||||
|
await expect(roomListView.getByRole("button").nth(3)).toHaveText(/empty room/);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should move room to the top on message when sorting by activity", async ({ page, bot }) => {
|
test("should move room to the top on message (chat section) when sorting by activity", async ({
|
||||||
|
page,
|
||||||
|
bot,
|
||||||
|
}) => {
|
||||||
const roomListView = getRoomList(page);
|
const roomListView = getRoomList(page);
|
||||||
|
|
||||||
await bot.sendMessage(unReadDmId, "Hello!");
|
await bot.sendMessage(unReadDmId, "Hello!");
|
||||||
|
|
||||||
await expect(roomListView.getByRole("option").first()).toHaveText(/unread dm/);
|
// Favourite + chat section headers are buttons + favourite room
|
||||||
|
await expect(roomListView.getByRole("button").nth(3)).toHaveText(/unread dm/);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -302,7 +310,7 @@ test.describe("Room list filters and sort", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
["People", "Rooms", "Favourite"].forEach((filter) => {
|
["People", "Rooms"].forEach((filter) => {
|
||||||
test(
|
test(
|
||||||
`should render the placeholder for ${filter} filter`,
|
`should render the placeholder for ${filter} filter`,
|
||||||
{ tag: "@screenshot" },
|
{ tag: "@screenshot" },
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { rejectToast } from "@element-hq/element-web-playwright-common";
|
import { closeReleaseAnnouncement, rejectToast } from "@element-hq/element-web-playwright-common";
|
||||||
|
|
||||||
import { test, expect } from "../../../element-web-test";
|
import { test, expect } from "../../../element-web-test";
|
||||||
import { getHeaderSection } from "./utils";
|
import { getHeaderSection } from "./utils";
|
||||||
@@ -19,6 +19,9 @@ test.describe("Header section of the room list", () => {
|
|||||||
// The toasts are displayed above the search section
|
// The toasts are displayed above the search section
|
||||||
await rejectToast(page, "Verify this device");
|
await rejectToast(page, "Verify this device");
|
||||||
await rejectToast(page, "Notifications");
|
await rejectToast(page, "Notifications");
|
||||||
|
|
||||||
|
// Close the release announcement about the new room list sections
|
||||||
|
await closeReleaseAnnouncement(page, "Introducing Sections");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should render the header section", { tag: "@screenshot" }, async ({ page, app, user }) => {
|
test("should render the header section", { tag: "@screenshot" }, async ({ page, app, user }) => {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import { assertRoomInSection, dragRoomToSection, getPrimaryFilters, getRoomList,
|
|||||||
test.describe("Room list sections", () => {
|
test.describe("Room list sections", () => {
|
||||||
test.use({
|
test.use({
|
||||||
displayName: "Alice",
|
displayName: "Alice",
|
||||||
labsFlags: ["feature_new_room_list", "feature_room_list_sections"],
|
labsFlags: ["feature_new_room_list"],
|
||||||
botCreateOpts: {
|
botCreateOpts: {
|
||||||
displayName: "BotBob",
|
displayName: "BotBob",
|
||||||
autoAcceptInvites: true,
|
autoAcceptInvites: true,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { type Page } from "@playwright/test";
|
import { type Page } from "@playwright/test";
|
||||||
import { rejectToast } from "@element-hq/element-web-playwright-common";
|
import { closeReleaseAnnouncement, rejectToast } from "@element-hq/element-web-playwright-common";
|
||||||
|
|
||||||
import { expect, test } from "../../../element-web-test";
|
import { expect, test } from "../../../element-web-test";
|
||||||
import { type Bot } from "../../../pages/bot";
|
import { type Bot } from "../../../pages/bot";
|
||||||
@@ -27,6 +27,9 @@ test.describe("Room list", () => {
|
|||||||
await rejectToast(page, "Verify this device");
|
await rejectToast(page, "Verify this device");
|
||||||
await rejectToast(page, "Notifications");
|
await rejectToast(page, "Notifications");
|
||||||
|
|
||||||
|
// Close the release announcement about the new room list sections
|
||||||
|
await closeReleaseAnnouncement(page, "Introducing Sections");
|
||||||
|
|
||||||
// focus the user menu to avoid to have hover decoration
|
// focus the user menu to avoid to have hover decoration
|
||||||
await page.getByRole("button", { name: "User menu" }).focus();
|
await page.getByRole("button", { name: "User menu" }).focus();
|
||||||
});
|
});
|
||||||
@@ -71,11 +74,11 @@ test.describe("Room list", () => {
|
|||||||
|
|
||||||
test("should open the more options menu", { tag: "@screenshot" }, async ({ page, app, user }) => {
|
test("should open the more options menu", { tag: "@screenshot" }, async ({ page, app, user }) => {
|
||||||
const roomListView = getRoomList(page);
|
const roomListView = getRoomList(page);
|
||||||
const roomItem = roomListView.getByRole("option", { name: "Open room room29" });
|
let roomItem = roomListView.getByRole("option", { name: "Open room room29" });
|
||||||
await roomItem.hover();
|
await roomItem.hover();
|
||||||
|
|
||||||
await expect(roomItem).toMatchScreenshot("room-list-item-hover.png");
|
await expect(roomItem).toMatchScreenshot("room-list-item-hover.png");
|
||||||
const roomItemMenu = roomItem.getByRole("button", { name: "More Options" });
|
let roomItemMenu = roomItem.getByRole("button", { name: "More Options" });
|
||||||
await roomItemMenu.click();
|
await roomItemMenu.click();
|
||||||
await expect(page).toMatchScreenshot("room-list-item-open-more-options.png");
|
await expect(page).toMatchScreenshot("room-list-item-open-more-options.png");
|
||||||
|
|
||||||
@@ -83,7 +86,9 @@ test.describe("Room list", () => {
|
|||||||
await page.getByRole("menuitemcheckbox", { name: "Favourited" }).click();
|
await page.getByRole("menuitemcheckbox", { name: "Favourited" }).click();
|
||||||
|
|
||||||
// Check that the room is favourited
|
// Check that the room is favourited
|
||||||
|
roomItem = roomListView.getByRole("gridcell", { name: "Open room room29" });
|
||||||
await roomItem.hover();
|
await roomItem.hover();
|
||||||
|
roomItemMenu = roomItem.getByRole("button", { name: "More Options" });
|
||||||
await roomItemMenu.click();
|
await roomItemMenu.click();
|
||||||
await expect(page.getByRole("menuitemcheckbox", { name: "Favourited" })).toBeChecked();
|
await expect(page.getByRole("menuitemcheckbox", { name: "Favourited" })).toBeChecked();
|
||||||
// It should show the invite dialog
|
// It should show the invite dialog
|
||||||
@@ -296,13 +301,14 @@ test.describe("Room list", () => {
|
|||||||
// @ts-ignore Visibility enum is not accessible
|
// @ts-ignore Visibility enum is not accessible
|
||||||
await app.client.createRoom({ name: "low priority room", visibility: "public" });
|
await app.client.createRoom({ name: "low priority room", visibility: "public" });
|
||||||
const roomListView = getRoomList(page);
|
const roomListView = getRoomList(page);
|
||||||
const publicRoom = roomListView.getByRole("option", { name: "low priority room" });
|
let publicRoom = roomListView.getByRole("option", { name: "low priority room" });
|
||||||
|
|
||||||
// Make room low priority
|
// Make room low priority
|
||||||
await publicRoom.click({ button: "right" });
|
await publicRoom.click({ button: "right" });
|
||||||
await page.getByRole("menuitemcheckbox", { name: "Low priority" }).click();
|
await page.getByRole("menuitemcheckbox", { name: "Low priority" }).click();
|
||||||
|
|
||||||
// Should have low priority decoration
|
// Should have low priority decoration
|
||||||
|
publicRoom = roomListView.getByRole("gridcell", { name: "low priority room" });
|
||||||
await expect(publicRoom.locator(".mx_RoomAvatarView_icon")).toHaveAccessibleName(
|
await expect(publicRoom.locator(".mx_RoomAvatarView_icon")).toHaveAccessibleName(
|
||||||
"This is a low priority room",
|
"This is a low priority room",
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { type Locator } from "@playwright/test";
|
import { type Locator } from "@playwright/test";
|
||||||
|
import { closeReleaseAnnouncement, rejectToast } from "@element-hq/element-web-playwright-common";
|
||||||
|
|
||||||
import { test, expect } from "../../../element-web-test";
|
import { test, expect } from "../../../element-web-test";
|
||||||
|
|
||||||
@@ -18,7 +19,12 @@ test.describe("Roles & Permissions room settings tab", () => {
|
|||||||
|
|
||||||
let settings: Locator;
|
let settings: Locator;
|
||||||
|
|
||||||
test.beforeEach(async ({ user, app }) => {
|
test.beforeEach(async ({ user, app, page }) => {
|
||||||
|
await rejectToast(page, "Verify this device");
|
||||||
|
await rejectToast(page, "Notifications");
|
||||||
|
// Close the release announcement about the new room list sections
|
||||||
|
await closeReleaseAnnouncement(page, "Introducing Sections");
|
||||||
|
|
||||||
await app.client.createRoom({
|
await app.client.createRoom({
|
||||||
name: roomName,
|
name: roomName,
|
||||||
power_level_content_override: {
|
power_level_content_override: {
|
||||||
|
|||||||
@@ -291,7 +291,7 @@ test.describe("Sliding Sync", () => {
|
|||||||
await checkOrder(["Room to Join", "Test Room"], page);
|
await checkOrder(["Room to Join", "Test Room"], page);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should show a favourite DM only in the favourite sublist", async ({ page, app }) => {
|
test("should show a favourite DM only in the favourite section", async ({ page, app }) => {
|
||||||
const roomId = await app.client.createRoom({
|
const roomId = await app.client.createRoom({
|
||||||
name: "Favourite DM",
|
name: "Favourite DM",
|
||||||
is_direct: true,
|
is_direct: true,
|
||||||
@@ -300,12 +300,9 @@ test.describe("Sliding Sync", () => {
|
|||||||
await client.setRoomTag(roomId, "m.favourite", { order: 0.5 });
|
await client.setRoomTag(roomId, "m.favourite", { order: 0.5 });
|
||||||
}, roomId);
|
}, roomId);
|
||||||
|
|
||||||
await getFilterExpandButton(page).click();
|
await expect(page.getByRole("button", { name: "Favourite DM" })).toBeVisible();
|
||||||
|
|
||||||
const primaryFilters = getPrimaryFilters(page);
|
const primaryFilters = getPrimaryFilters(page);
|
||||||
await primaryFilters.getByRole("option", { name: "Favourites" }).click();
|
|
||||||
|
|
||||||
await expect(page.getByRole("option", { name: "Favourite DM" })).toBeVisible();
|
|
||||||
|
|
||||||
await primaryFilters.getByRole("option", { name: "People" }).click();
|
await primaryFilters.getByRole("option", { name: "People" }).click();
|
||||||
|
|
||||||
await expect(page.getByRole("option", { name: "Favourite DM" })).not.toBeAttached();
|
await expect(page.getByRole("option", { name: "Favourite DM" })).not.toBeAttached();
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ Please see LICENSE files in the repository root for full details.
|
|||||||
import { readFile } from "node:fs/promises";
|
import { readFile } from "node:fs/promises";
|
||||||
import { fileURLToPath } from "node:url";
|
import { fileURLToPath } from "node:url";
|
||||||
import { type Page } from "@playwright/test";
|
import { type Page } from "@playwright/test";
|
||||||
|
import { closeReleaseAnnouncement, rejectToast } from "@element-hq/element-web-playwright-common";
|
||||||
|
|
||||||
import type { EventType, Preset } from "matrix-js-sdk/src/matrix";
|
import type { EventType, Preset } from "matrix-js-sdk/src/matrix";
|
||||||
import { SettingLevel } from "../../../src/settings/SettingLevel";
|
import { SettingLevel } from "../../../src/settings/SettingLevel";
|
||||||
@@ -132,6 +133,11 @@ test.describe("Element Call", () => {
|
|||||||
SettingLevel.DEVICE,
|
SettingLevel.DEVICE,
|
||||||
new URL("/widget.html#", page.url()).toString(),
|
new URL("/widget.html#", page.url()).toString(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await rejectToast(page, "Verify this device");
|
||||||
|
await rejectToast(page, "Notifications");
|
||||||
|
// Close the release announcement about the new room list sections
|
||||||
|
await closeReleaseAnnouncement(page, "Introducing Sections");
|
||||||
});
|
});
|
||||||
|
|
||||||
test.describe("Group Chat", () => {
|
test.describe("Group Chat", () => {
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 91 KiB |
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 55 KiB |
@@ -1582,7 +1582,6 @@
|
|||||||
"notifications": "Enable the notifications panel in the room header",
|
"notifications": "Enable the notifications panel in the room header",
|
||||||
"render_reaction_images": "Render custom images in reactions",
|
"render_reaction_images": "Render custom images in reactions",
|
||||||
"render_reaction_images_description": "Sometimes referred to as \"custom emojis\".",
|
"render_reaction_images_description": "Sometimes referred to as \"custom emojis\".",
|
||||||
"room_list_sections": "Room list sections",
|
|
||||||
"sliding_sync": "Sliding Sync mode",
|
"sliding_sync": "Sliding Sync mode",
|
||||||
"sliding_sync_description": "Under active development, cannot be disabled. Currently, not compatible with Element Call.",
|
"sliding_sync_description": "Under active development, cannot be disabled. Currently, not compatible with Element Call.",
|
||||||
"sliding_sync_disabled_notice": "Sign in again to disable",
|
"sliding_sync_disabled_notice": "Sign in again to disable",
|
||||||
|
|||||||
@@ -227,7 +227,6 @@ export interface Settings {
|
|||||||
"feature_render_reaction_images": IFeature;
|
"feature_render_reaction_images": IFeature;
|
||||||
"feature_new_room_list": IFeature;
|
"feature_new_room_list": IFeature;
|
||||||
"feature_retention": IFeature;
|
"feature_retention": IFeature;
|
||||||
"feature_room_list_sections": IFeature;
|
|
||||||
"feature_ask_to_join": IFeature;
|
"feature_ask_to_join": IFeature;
|
||||||
"feature_notifications": IFeature;
|
"feature_notifications": IFeature;
|
||||||
"feature_msc4362_encrypted_state_events": IFeature;
|
"feature_msc4362_encrypted_state_events": IFeature;
|
||||||
@@ -665,15 +664,6 @@ export const SETTINGS: Settings = {
|
|||||||
default: true,
|
default: true,
|
||||||
controller: new ReloadOnChangeController(),
|
controller: new ReloadOnChangeController(),
|
||||||
},
|
},
|
||||||
"feature_room_list_sections": {
|
|
||||||
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG_PRIORITISED,
|
|
||||||
labsGroup: LabGroup.Ui,
|
|
||||||
displayName: _td("labs|room_list_sections"),
|
|
||||||
description: _td("labs|under_active_development"),
|
|
||||||
isFeature: true,
|
|
||||||
default: false,
|
|
||||||
controller: new ReloadOnChangeController(),
|
|
||||||
},
|
|
||||||
"feature_login_with_qr": {
|
"feature_login_with_qr": {
|
||||||
supportedLevels: [SettingLevel.CONFIG],
|
supportedLevels: [SettingLevel.CONFIG],
|
||||||
labsGroup: LabGroup.Ui,
|
labsGroup: LabGroup.Ui,
|
||||||
|
|||||||
@@ -173,10 +173,7 @@ export class RoomListStoreV3Class extends AsyncStoreWithClient<EmptyObject> {
|
|||||||
public getSortedRoomsInActiveSpace(filterKeys?: FilterKey[]): RoomsResult {
|
public getSortedRoomsInActiveSpace(filterKeys?: FilterKey[]): RoomsResult {
|
||||||
const spaceId = SpaceStore.instance.activeSpace;
|
const spaceId = SpaceStore.instance.activeSpace;
|
||||||
|
|
||||||
const areSectionsEnabled = SettingsStore.getValue("feature_room_list_sections");
|
const sections = this.getSections(filterKeys);
|
||||||
const sections = areSectionsEnabled
|
|
||||||
? this.getSections(filterKeys)
|
|
||||||
: [{ tag: CHATS_TAG, rooms: Array.from(this.roomSkipList?.getRoomsInActiveSpace(filterKeys) ?? []) }];
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
spaceId: spaceId,
|
spaceId: spaceId,
|
||||||
|
|||||||
@@ -243,9 +243,7 @@ export class RoomListHeaderViewModel
|
|||||||
};
|
};
|
||||||
|
|
||||||
public onReleaseAnnouncementChanged = (): void => {
|
public onReleaseAnnouncementChanged = (): void => {
|
||||||
const isSectionFeatureEnabled = SettingsStore.getValue("feature_room_list_sections");
|
|
||||||
const displaySectionReleaseAnnouncement =
|
const displaySectionReleaseAnnouncement =
|
||||||
isSectionFeatureEnabled &&
|
|
||||||
ReleaseAnnouncementStore.instance.getReleaseAnnouncement() === "room_list_section";
|
ReleaseAnnouncementStore.instance.getReleaseAnnouncement() === "room_list_section";
|
||||||
this.snapshot.merge({ displaySectionReleaseAnnouncement });
|
this.snapshot.merge({ displaySectionReleaseAnnouncement });
|
||||||
};
|
};
|
||||||
@@ -310,35 +308,27 @@ function computeHeaderSpaceState(
|
|||||||
spaceStore: SpaceStoreClass,
|
spaceStore: SpaceStoreClass,
|
||||||
matrixClient: MatrixClient,
|
matrixClient: MatrixClient,
|
||||||
): Omit<RoomListHeaderViewSnapshot, "activeSortOption" | "isMessagePreviewEnabled"> {
|
): Omit<RoomListHeaderViewSnapshot, "activeSortOption" | "isMessagePreviewEnabled"> {
|
||||||
const isSectionFeatureEnabled = SettingsStore.getValue("feature_room_list_sections");
|
|
||||||
const displaySectionReleaseAnnouncement =
|
const displaySectionReleaseAnnouncement =
|
||||||
isSectionFeatureEnabled && ReleaseAnnouncementStore.instance.getReleaseAnnouncement() === "room_list_section";
|
ReleaseAnnouncementStore.instance.getReleaseAnnouncement() === "room_list_section";
|
||||||
|
|
||||||
const activeSpace = spaceStore.activeSpaceRoom;
|
const activeSpace = spaceStore.activeSpaceRoom;
|
||||||
const title = getHeaderTitle(spaceStore);
|
const title = getHeaderTitle(spaceStore);
|
||||||
|
|
||||||
const canCreateRoom = hasCreateRoomRights(matrixClient, activeSpace);
|
const canCreateRoom = hasCreateRoomRights(matrixClient, activeSpace);
|
||||||
const canCreateVideoRoom = getCanCreateVideoRoom(canCreateRoom);
|
const canCreateVideoRoom = getCanCreateVideoRoom(canCreateRoom);
|
||||||
const displayComposeMenu = isSectionFeatureEnabled || canCreateRoom;
|
|
||||||
const displaySpaceMenu = Boolean(activeSpace);
|
const displaySpaceMenu = Boolean(activeSpace);
|
||||||
const canInviteInSpace = Boolean(
|
const canInviteInSpace = Boolean(
|
||||||
activeSpace?.getJoinRule() === JoinRule.Public || activeSpace?.canInvite(matrixClient.getSafeUserId()),
|
activeSpace?.getJoinRule() === JoinRule.Public || activeSpace?.canInvite(matrixClient.getSafeUserId()),
|
||||||
);
|
);
|
||||||
const canAccessSpaceSettings = Boolean(activeSpace && shouldShowSpaceSettings(activeSpace));
|
const canAccessSpaceSettings = Boolean(activeSpace && shouldShowSpaceSettings(activeSpace));
|
||||||
|
|
||||||
const useComposeIcon = !isSectionFeatureEnabled;
|
|
||||||
const canCreateSection = isSectionFeatureEnabled;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title,
|
title,
|
||||||
canCreateRoom,
|
canCreateRoom,
|
||||||
canCreateVideoRoom,
|
canCreateVideoRoom,
|
||||||
displayComposeMenu,
|
|
||||||
displaySpaceMenu,
|
displaySpaceMenu,
|
||||||
canInviteInSpace,
|
canInviteInSpace,
|
||||||
canAccessSpaceSettings,
|
canAccessSpaceSettings,
|
||||||
canCreateSection,
|
|
||||||
useComposeIcon,
|
|
||||||
displaySectionReleaseAnnouncement,
|
displaySectionReleaseAnnouncement,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -288,10 +288,8 @@ export class RoomListItemViewModel
|
|||||||
const callType =
|
const callType =
|
||||||
call?.callType === CallType.Voice ? "voice" : call?.callType === CallType.Video ? "video" : undefined;
|
call?.callType === CallType.Voice ? "voice" : call?.callType === CallType.Video ? "video" : undefined;
|
||||||
|
|
||||||
const canMoveToSection = SettingsStore.getValue("feature_room_list_sections");
|
|
||||||
|
|
||||||
// Build sections list for the "Move to section" submenu
|
// Build sections list for the "Move to section" submenu
|
||||||
const sections: Section[] = canMoveToSection ? RoomListItemViewModel.buildSections(roomTags) : [];
|
const sections: Section[] = RoomListItemViewModel.buildSections(roomTags);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: room.roomId,
|
id: room.roomId,
|
||||||
@@ -320,7 +318,6 @@ export class RoomListItemViewModel
|
|||||||
canMarkAsRead,
|
canMarkAsRead,
|
||||||
canMarkAsUnread,
|
canMarkAsUnread,
|
||||||
roomNotifState,
|
roomNotifState,
|
||||||
canMoveToSection,
|
|
||||||
sections,
|
sections,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ import { keepIfSame } from "../../utils/keepIfSame";
|
|||||||
import { DefaultTagID } from "../../stores/room-list-v3/skip-list/tag";
|
import { DefaultTagID } from "../../stores/room-list-v3/skip-list/tag";
|
||||||
import { RoomListSectionHeaderViewModel } from "./RoomListSectionHeaderViewModel";
|
import { RoomListSectionHeaderViewModel } from "./RoomListSectionHeaderViewModel";
|
||||||
import { getCustomSectionData, isCustomSectionTag, CHATS_TAG } from "../../stores/room-list-v3/section";
|
import { getCustomSectionData, isCustomSectionTag, CHATS_TAG } from "../../stores/room-list-v3/section";
|
||||||
import SettingsStore from "../../settings/SettingsStore";
|
|
||||||
import { tagRoom } from "../../utils/room/tagRoom";
|
import { tagRoom } from "../../utils/room/tagRoom";
|
||||||
import { getSectionTagForRoom } from "../../utils/room/getSectionTagForRoom";
|
import { getSectionTagForRoom } from "../../utils/room/getSectionTagForRoom";
|
||||||
|
|
||||||
@@ -64,10 +63,8 @@ const filterKeyToIdMap: Map<FilterEnum, FilterId> = new Map([
|
|||||||
[FilterEnum.UnreadFilter, "unread"],
|
[FilterEnum.UnreadFilter, "unread"],
|
||||||
[FilterEnum.PeopleFilter, "people"],
|
[FilterEnum.PeopleFilter, "people"],
|
||||||
[FilterEnum.RoomsFilter, "rooms"],
|
[FilterEnum.RoomsFilter, "rooms"],
|
||||||
[FilterEnum.FavouriteFilter, "favourite"],
|
|
||||||
[FilterEnum.MentionsFilter, "mentions"],
|
[FilterEnum.MentionsFilter, "mentions"],
|
||||||
[FilterEnum.InvitesFilter, "invites"],
|
[FilterEnum.InvitesFilter, "invites"],
|
||||||
[FilterEnum.LowPriorityFilter, "low_priority"],
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const TAG_TO_TITLE_MAP: Record<string, string> = {
|
const TAG_TO_TITLE_MAP: Record<string, string> = {
|
||||||
@@ -146,11 +143,7 @@ export class RoomListViewModel
|
|||||||
const roomsResult = RoomListStoreV3.instance.getSortedRoomsInActiveSpace(undefined);
|
const roomsResult = RoomListStoreV3.instance.getSortedRoomsInActiveSpace(undefined);
|
||||||
const canCreateRoom = hasCreateRoomRights(props.client, activeSpace);
|
const canCreateRoom = hasCreateRoomRights(props.client, activeSpace);
|
||||||
|
|
||||||
// Remove favourite and low priority filters if sections are enabled, as they are redundant with the sections
|
const filterIds = [...filterKeyToIdMap.values()];
|
||||||
const areSectionsEnabled = SettingsStore.getValue("feature_room_list_sections");
|
|
||||||
const filterIds = [...filterKeyToIdMap.values()].filter(
|
|
||||||
(id) => !areSectionsEnabled || (id !== "favourite" && id !== "low_priority"),
|
|
||||||
);
|
|
||||||
|
|
||||||
// By default, all sections are expanded
|
// By default, all sections are expanded
|
||||||
const { sections, isFlatList } = computeSections(roomsResult, (tag) => true);
|
const { sections, isFlatList } = computeSections(roomsResult, (tag) => true);
|
||||||
@@ -756,8 +749,8 @@ export class RoomListViewModel
|
|||||||
* @param isFlatList - Whether the room list is currently displayed as a flat list
|
* @param isFlatList - Whether the room list is currently displayed as a flat list
|
||||||
*/
|
*/
|
||||||
private notifyCollapseState(isFlatList: boolean): void {
|
private notifyCollapseState(isFlatList: boolean): void {
|
||||||
// Hide collapse/expand all button if sections are disabled or if it's a flat list
|
// Hide collapse/expand all button if it's a flat list
|
||||||
if (!SettingsStore.getValue("feature_room_list_sections") || isFlatList) {
|
if (isFlatList) {
|
||||||
dispatcher.dispatch<RoomListSectionsCollapseStateChangedPayload>({
|
dispatcher.dispatch<RoomListSectionsCollapseStateChangedPayload>({
|
||||||
action: Action.RoomListSectionsCollapseStateChanged,
|
action: Action.RoomListSectionsCollapseStateChanged,
|
||||||
collapseSections: undefined,
|
collapseSections: undefined,
|
||||||
|
|||||||
@@ -929,7 +929,6 @@ describe("RoomListStoreV3", () => {
|
|||||||
describe("Sections", () => {
|
describe("Sections", () => {
|
||||||
function enableSections(): void {
|
function enableSections(): void {
|
||||||
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting: string) => {
|
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting: string) => {
|
||||||
if (setting === "feature_room_list_sections") return true;
|
|
||||||
if (setting === "RoomList.OrderedCustomSections") return [];
|
if (setting === "RoomList.OrderedCustomSections") return [];
|
||||||
if (setting === "RoomList.CustomSectionData") return {};
|
if (setting === "RoomList.CustomSectionData") return {};
|
||||||
return false;
|
return false;
|
||||||
@@ -948,26 +947,7 @@ describe("RoomListStoreV3", () => {
|
|||||||
return { client, rooms };
|
return { client, rooms };
|
||||||
}
|
}
|
||||||
|
|
||||||
it("returns a single chats section when sections feature is disabled", async () => {
|
it("returns three sections in the correct order", async () => {
|
||||||
const { rooms } = getClientAndRooms();
|
|
||||||
// Mark some rooms as favourite so we can verify they are NOT split out
|
|
||||||
[0, 1, 2].forEach((i) => {
|
|
||||||
rooms[i].tags[DefaultTagID.Favourite] = {};
|
|
||||||
});
|
|
||||||
|
|
||||||
const store = new RoomListStoreV3Class(dispatcher);
|
|
||||||
await store.start();
|
|
||||||
|
|
||||||
const result = store.getSortedRoomsInActiveSpace();
|
|
||||||
expect(result.sections).toHaveLength(1);
|
|
||||||
expect(result.sections[0].tag).toBe(CHATS_TAG);
|
|
||||||
// All rooms, including favourites, are in the single section
|
|
||||||
for (const i of [0, 1, 2]) {
|
|
||||||
expect(result.sections[0].rooms).toContain(rooms[i]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it("returns three sections in the correct order when enabled", async () => {
|
|
||||||
enableSections();
|
enableSections();
|
||||||
getClientAndRooms();
|
getClientAndRooms();
|
||||||
|
|
||||||
@@ -1229,7 +1209,6 @@ describe("RoomListStoreV3", () => {
|
|||||||
const customTag = "element.io.section.custom";
|
const customTag = "element.io.section.custom";
|
||||||
|
|
||||||
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting: string) => {
|
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting: string) => {
|
||||||
if (setting === "feature_room_list_sections") return true;
|
|
||||||
if (setting === "RoomList.OrderedCustomSections") return [];
|
if (setting === "RoomList.OrderedCustomSections") return [];
|
||||||
if (setting === "RoomList.CustomSectionData") return {};
|
if (setting === "RoomList.CustomSectionData") return {};
|
||||||
return false;
|
return false;
|
||||||
@@ -1244,7 +1223,6 @@ describe("RoomListStoreV3", () => {
|
|||||||
// Mark a room with the custom tag and update the settings
|
// Mark a room with the custom tag and update the settings
|
||||||
rooms[0].tags = { [customTag]: { order: 0 } };
|
rooms[0].tags = { [customTag]: { order: 0 } };
|
||||||
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting: string) => {
|
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting: string) => {
|
||||||
if (setting === "feature_room_list_sections") return true;
|
|
||||||
if (setting === "RoomList.OrderedCustomSections") return [customTag];
|
if (setting === "RoomList.OrderedCustomSections") return [customTag];
|
||||||
if (setting === "RoomList.CustomSectionData")
|
if (setting === "RoomList.CustomSectionData")
|
||||||
return { [customTag]: { tag: customTag, name: "Custom" } };
|
return { [customTag]: { tag: customTag, name: "Custom" } };
|
||||||
|
|||||||
@@ -86,7 +86,6 @@ describe("RoomListHeaderViewModel", () => {
|
|||||||
|
|
||||||
const snapshot = vm.getSnapshot();
|
const snapshot = vm.getSnapshot();
|
||||||
expect(snapshot.title).toBe("Home");
|
expect(snapshot.title).toBe("Home");
|
||||||
expect(snapshot.displayComposeMenu).toBe(true);
|
|
||||||
expect(snapshot.displaySpaceMenu).toBe(false);
|
expect(snapshot.displaySpaceMenu).toBe(false);
|
||||||
expect(snapshot.canCreateRoom).toBe(true);
|
expect(snapshot.canCreateRoom).toBe(true);
|
||||||
expect(snapshot.canCreateVideoRoom).toBe(true);
|
expect(snapshot.canCreateVideoRoom).toBe(true);
|
||||||
@@ -123,28 +122,6 @@ describe("RoomListHeaderViewModel", () => {
|
|||||||
expect(vm.getSnapshot().activeSortOption).toBe("alphabetical");
|
expect(vm.getSnapshot().activeSortOption).toBe("alphabetical");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should hide compose menu when user cannot create rooms", () => {
|
|
||||||
mocked(hasCreateRoomRights).mockReturnValue(false);
|
|
||||||
|
|
||||||
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
|
|
||||||
|
|
||||||
const snapshot = vm.getSnapshot();
|
|
||||||
expect(snapshot.displayComposeMenu).toBe(false);
|
|
||||||
expect(snapshot.canCreateRoom).toBe(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should display compose menu when section feature is enabled@", () => {
|
|
||||||
jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName: string) => {
|
|
||||||
if (settingName === "feature_room_list_sections") return true;
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
|
|
||||||
|
|
||||||
const snapshot = vm.getSnapshot();
|
|
||||||
expect(snapshot.displayComposeMenu).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should show invite option when space is public", () => {
|
it("should show invite option when space is public", () => {
|
||||||
jest.spyOn(SpaceStore.instance, "activeSpace", "get").mockReturnValue(mockSpace.roomId);
|
jest.spyOn(SpaceStore.instance, "activeSpace", "get").mockReturnValue(mockSpace.roomId);
|
||||||
jest.spyOn(SpaceStore.instance, "activeSpaceRoom", "get").mockReturnValue(mockSpace);
|
jest.spyOn(SpaceStore.instance, "activeSpaceRoom", "get").mockReturnValue(mockSpace);
|
||||||
@@ -179,28 +156,7 @@ describe("RoomListHeaderViewModel", () => {
|
|||||||
expect(vm.getSnapshot().isMessagePreviewEnabled).toBe(true);
|
expect(vm.getSnapshot().isMessagePreviewEnabled).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each([
|
|
||||||
[true, true, false],
|
|
||||||
[false, false, true],
|
|
||||||
])(
|
|
||||||
"when feature_room_list_sections is %s: canCreateSection=%s, useComposeIcon=%s",
|
|
||||||
(featureEnabled, expectedCanCreateSection, expectedUseComposeIcon) => {
|
|
||||||
jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName: string) => {
|
|
||||||
if (settingName === "feature_room_list_sections") return featureEnabled;
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
|
|
||||||
expect(vm.getSnapshot().canCreateSection).toBe(expectedCanCreateSection);
|
|
||||||
expect(vm.getSnapshot().useComposeIcon).toBe(expectedUseComposeIcon);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
it("should set displaySectionReleaseAnnouncement to true when sections feature is enabled and announcement is active", () => {
|
it("should set displaySectionReleaseAnnouncement to true when sections feature is enabled and announcement is active", () => {
|
||||||
jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName: string) => {
|
|
||||||
if (settingName === "feature_room_list_sections") return true;
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
jest.spyOn(ReleaseAnnouncementStore.instance, "getReleaseAnnouncement").mockReturnValue(
|
jest.spyOn(ReleaseAnnouncementStore.instance, "getReleaseAnnouncement").mockReturnValue(
|
||||||
"room_list_section",
|
"room_list_section",
|
||||||
);
|
);
|
||||||
@@ -208,15 +164,6 @@ describe("RoomListHeaderViewModel", () => {
|
|||||||
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
|
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
|
||||||
expect(vm.getSnapshot().displaySectionReleaseAnnouncement).toBe(true);
|
expect(vm.getSnapshot().displaySectionReleaseAnnouncement).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should set displaySectionReleaseAnnouncement to false when sections feature is disabled", () => {
|
|
||||||
jest.spyOn(ReleaseAnnouncementStore.instance, "getReleaseAnnouncement").mockReturnValue(
|
|
||||||
"room_list_section",
|
|
||||||
);
|
|
||||||
|
|
||||||
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
|
|
||||||
expect(vm.getSnapshot().displaySectionReleaseAnnouncement).toBe(false);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("event listeners", () => {
|
describe("event listeners", () => {
|
||||||
|
|||||||
@@ -509,20 +509,6 @@ describe("RoomListItemViewModel", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("canMoveToSection", () => {
|
|
||||||
it.each([
|
|
||||||
[true, true],
|
|
||||||
[false, false],
|
|
||||||
])("should be %s when feature_room_list_sections is %s", (featureEnabled, expected) => {
|
|
||||||
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting) => {
|
|
||||||
if (setting === "feature_room_list_sections") return featureEnabled;
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
viewModel = new RoomListItemViewModel({ room, client: matrixClient });
|
|
||||||
expect(viewModel.getSnapshot().canMoveToSection).toBe(expected);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("Actions", () => {
|
describe("Actions", () => {
|
||||||
it("should dispatch view room action on openRoom", () => {
|
it("should dispatch view room action on openRoom", () => {
|
||||||
viewModel = new RoomListItemViewModel({ room, client: matrixClient });
|
viewModel = new RoomListItemViewModel({ room, client: matrixClient });
|
||||||
@@ -631,10 +617,6 @@ describe("RoomListItemViewModel", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should include sections from orderedSectionTags excluding CHATS_TAG, favourite, and low priority", () => {
|
it("should include sections from orderedSectionTags excluding CHATS_TAG, favourite, and low priority", () => {
|
||||||
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting) => {
|
|
||||||
if (setting === "feature_room_list_sections") return true;
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
viewModel = new RoomListItemViewModel({ room, client: matrixClient });
|
viewModel = new RoomListItemViewModel({ room, client: matrixClient });
|
||||||
|
|
||||||
const sections = viewModel.getSnapshot().sections;
|
const sections = viewModel.getSnapshot().sections;
|
||||||
@@ -643,10 +625,7 @@ describe("RoomListItemViewModel", () => {
|
|||||||
|
|
||||||
it("should mark the room current section as selected", () => {
|
it("should mark the room current section as selected", () => {
|
||||||
room.tags = { [customTag]: { order: 0 } };
|
room.tags = { [customTag]: { order: 0 } };
|
||||||
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting) => {
|
|
||||||
if (setting === "feature_room_list_sections") return true;
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
viewModel = new RoomListItemViewModel({ room, client: matrixClient });
|
viewModel = new RoomListItemViewModel({ room, client: matrixClient });
|
||||||
|
|
||||||
const sections = viewModel.getSnapshot().sections;
|
const sections = viewModel.getSnapshot().sections;
|
||||||
@@ -655,7 +634,6 @@ describe("RoomListItemViewModel", () => {
|
|||||||
|
|
||||||
it("should use custom section name from CustomSectionData", () => {
|
it("should use custom section name from CustomSectionData", () => {
|
||||||
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting) => {
|
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting) => {
|
||||||
if (setting === "feature_room_list_sections") return true;
|
|
||||||
if (setting === "RoomList.CustomSectionData")
|
if (setting === "RoomList.CustomSectionData")
|
||||||
return { [customTag]: { name: "My Custom Section", tag: customTag } };
|
return { [customTag]: { name: "My Custom Section", tag: customTag } };
|
||||||
return false;
|
return false;
|
||||||
@@ -672,10 +650,6 @@ describe("RoomListItemViewModel", () => {
|
|||||||
if (setting === "RoomList.OrderedCustomSections") watchCallback = callback;
|
if (setting === "RoomList.OrderedCustomSections") watchCallback = callback;
|
||||||
return "watcher-id";
|
return "watcher-id";
|
||||||
});
|
});
|
||||||
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting) => {
|
|
||||||
if (setting === "feature_room_list_sections") return true;
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
viewModel = new RoomListItemViewModel({ room, client: matrixClient });
|
viewModel = new RoomListItemViewModel({ room, client: matrixClient });
|
||||||
expect(viewModel.getSnapshot().sections).toHaveLength(1);
|
expect(viewModel.getSnapshot().sections).toHaveLength(1);
|
||||||
|
|||||||
@@ -480,20 +480,6 @@ describe("RoomListViewModel", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("notifyCollapseState", () => {
|
|
||||||
it("should dispatch collapseSections=undefined when feature_room_list_sections is disabled", () => {
|
|
||||||
viewModel = new RoomListViewModel({ client: matrixClient });
|
|
||||||
|
|
||||||
const dispatchSpy = jest.spyOn(dispatcher, "dispatch");
|
|
||||||
RoomListStoreV3.instance.emit(RoomListStoreV3Event.ListsUpdate);
|
|
||||||
|
|
||||||
expect(dispatchSpy).toHaveBeenCalledWith({
|
|
||||||
action: Action.RoomListSectionsCollapseStateChanged,
|
|
||||||
collapseSections: undefined,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("Keyboard navigation (ViewRoomDelta)", () => {
|
describe("Keyboard navigation (ViewRoomDelta)", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
// stubClient sets up MatrixClientPeg which is needed when ViewRoom action is dispatched
|
// stubClient sets up MatrixClientPeg which is needed when ViewRoom action is dispatched
|
||||||
@@ -724,7 +710,7 @@ describe("RoomListViewModel", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Sections (feature_room_list_sections)", () => {
|
describe("Sections", () => {
|
||||||
let favRoom1: Room;
|
let favRoom1: Room;
|
||||||
let favRoom2: Room;
|
let favRoom2: Room;
|
||||||
let lowPriorityRoom: Room;
|
let lowPriorityRoom: Room;
|
||||||
@@ -732,11 +718,6 @@ describe("RoomListViewModel", () => {
|
|||||||
let regularRoom2: Room;
|
let regularRoom2: Room;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting: string) => {
|
|
||||||
if (setting === "feature_room_list_sections") return true;
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
favRoom1 = mkStubRoom("!fav1:server", "Fav 1", matrixClient);
|
favRoom1 = mkStubRoom("!fav1:server", "Fav 1", matrixClient);
|
||||||
favRoom2 = mkStubRoom("!fav2:server", "Fav 2", matrixClient);
|
favRoom2 = mkStubRoom("!fav2:server", "Fav 2", matrixClient);
|
||||||
lowPriorityRoom = mkStubRoom("!low1:server", "Low 1", matrixClient);
|
lowPriorityRoom = mkStubRoom("!low1:server", "Low 1", matrixClient);
|
||||||
@@ -1030,7 +1011,6 @@ describe("RoomListViewModel", () => {
|
|||||||
mkStubRoom("!space:server", "My Space", matrixClient),
|
mkStubRoom("!space:server", "My Space", matrixClient),
|
||||||
]);
|
]);
|
||||||
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting: string) => {
|
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting: string) => {
|
||||||
if (setting === "feature_room_list_sections") return true;
|
|
||||||
if (setting === "RoomList.CustomSectionData")
|
if (setting === "RoomList.CustomSectionData")
|
||||||
return {
|
return {
|
||||||
[customTag]: { tag: customTag, name: "My Section", spaceId: "!space:server" },
|
[customTag]: { tag: customTag, name: "My Section", spaceId: "!space:server" },
|
||||||
@@ -1041,7 +1021,6 @@ describe("RoomListViewModel", () => {
|
|||||||
|
|
||||||
it("shows an empty custom section when viewing its originating space", () => {
|
it("shows an empty custom section when viewing its originating space", () => {
|
||||||
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting: string) => {
|
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting: string) => {
|
||||||
if (setting === "feature_room_list_sections") return true;
|
|
||||||
if (setting === "RoomList.CustomSectionData")
|
if (setting === "RoomList.CustomSectionData")
|
||||||
return { [customTag]: { tag: customTag, name: "My Section", spaceId: MetaSpace.Home } };
|
return { [customTag]: { tag: customTag, name: "My Section", spaceId: MetaSpace.Home } };
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 55 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 63 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 63 KiB |
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 59 KiB |
@@ -135,10 +135,7 @@
|
|||||||
"no_chats": "No chats yet",
|
"no_chats": "No chats yet",
|
||||||
"no_chats_description": "Get started by messaging someone or by creating a room",
|
"no_chats_description": "Get started by messaging someone or by creating a room",
|
||||||
"no_chats_description_no_room_rights": "Get started by messaging someone",
|
"no_chats_description_no_room_rights": "Get started by messaging someone",
|
||||||
"no_favourites": "You don't have favourite chats yet",
|
|
||||||
"no_favourites_description": "You can add a chat to your favourites in the chat settings",
|
|
||||||
"no_invites": "You don't have any unread invites",
|
"no_invites": "You don't have any unread invites",
|
||||||
"no_lowpriority": "You don't have any low priority rooms",
|
|
||||||
"no_mentions": "You don't have any unread mentions",
|
"no_mentions": "You don't have any unread mentions",
|
||||||
"no_people": "You don’t have direct chats with anyone yet",
|
"no_people": "You don’t have direct chats with anyone yet",
|
||||||
"no_people_description": "You can deselect filters in order to see your other chats",
|
"no_people_description": "You can deselect filters in order to see your other chats",
|
||||||
@@ -151,9 +148,7 @@
|
|||||||
"expand_all_sections": "Expand all sections",
|
"expand_all_sections": "Expand all sections",
|
||||||
"expand_filters": "Expand filter list",
|
"expand_filters": "Expand filter list",
|
||||||
"filters": {
|
"filters": {
|
||||||
"favourite": "Favourites",
|
|
||||||
"invites": "Invites",
|
"invites": "Invites",
|
||||||
"low_priority": "Low priority",
|
|
||||||
"mentions": "Mentions",
|
"mentions": "Mentions",
|
||||||
"people": "People",
|
"people": "People",
|
||||||
"rooms": "Rooms",
|
"rooms": "Rooms",
|
||||||
|
|||||||
@@ -91,12 +91,6 @@ export const NoSpaceMenu: Story = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const NoComposeMenu: Story = {
|
|
||||||
args: {
|
|
||||||
displayComposeMenu: false,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export const LongTitle: Story = {
|
export const LongTitle: Story = {
|
||||||
decorators: [
|
decorators: [
|
||||||
(Story) => (
|
(Story) => (
|
||||||
@@ -110,12 +104,6 @@ export const LongTitle: Story = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PlusIcon: Story = {
|
|
||||||
args: {
|
|
||||||
useComposeIcon: false,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export const CollapseSections: Story = {
|
export const CollapseSections: Story = {
|
||||||
args: {
|
args: {
|
||||||
collapseSections: "collapse",
|
collapseSections: "collapse",
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import React from "react";
|
|||||||
|
|
||||||
import * as stories from "./RoomListHeaderView.stories";
|
import * as stories from "./RoomListHeaderView.stories";
|
||||||
|
|
||||||
const { Default, NoComposeMenu, NoSpaceMenu, CollapseSections, ExpandSections } = composeStories(stories);
|
const { Default, NoSpaceMenu, CollapseSections, ExpandSections } = composeStories(stories);
|
||||||
|
|
||||||
describe("RoomListHeaderView", () => {
|
describe("RoomListHeaderView", () => {
|
||||||
it("renders the default state", () => {
|
it("renders the default state", () => {
|
||||||
@@ -20,11 +20,6 @@ describe("RoomListHeaderView", () => {
|
|||||||
expect(container).toMatchSnapshot();
|
expect(container).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("renders without compose menu", () => {
|
|
||||||
const { container } = render(<NoComposeMenu />);
|
|
||||||
expect(container).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("renders without space menu", () => {
|
it("renders without space menu", () => {
|
||||||
const { container } = render(<NoSpaceMenu />);
|
const { container } = render(<NoSpaceMenu />);
|
||||||
expect(container).toMatchSnapshot();
|
expect(container).toMatchSnapshot();
|
||||||
|
|||||||
@@ -7,8 +7,6 @@
|
|||||||
|
|
||||||
import React, { type JSX } from "react";
|
import React, { type JSX } from "react";
|
||||||
import { IconButton, H1 } from "@vector-im/compound-web";
|
import { IconButton, H1 } from "@vector-im/compound-web";
|
||||||
import ComposeIcon from "@vector-im/compound-design-tokens/assets/web/icons/compose";
|
|
||||||
import PlusIcon from "@vector-im/compound-design-tokens/assets/web/icons/plus";
|
|
||||||
import { CollapseAllIcon, ExpandAllIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
|
import { CollapseAllIcon, ExpandAllIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||||
|
|
||||||
import { type ViewModel, useViewModel } from "../../core/viewmodel";
|
import { type ViewModel, useViewModel } from "../../core/viewmodel";
|
||||||
@@ -32,11 +30,6 @@ export interface RoomListHeaderViewSnapshot {
|
|||||||
* The title of the room list
|
* The title of the room list
|
||||||
*/
|
*/
|
||||||
title: string;
|
title: string;
|
||||||
/**
|
|
||||||
* Whether to display the compose menu
|
|
||||||
* True if the user can create rooms
|
|
||||||
*/
|
|
||||||
displayComposeMenu: boolean;
|
|
||||||
/**
|
/**
|
||||||
* Whether to display the space menu
|
* Whether to display the space menu
|
||||||
* True if there is an active space
|
* True if there is an active space
|
||||||
@@ -66,14 +59,6 @@ export interface RoomListHeaderViewSnapshot {
|
|||||||
* Whether message previews are enabled in the room list.
|
* Whether message previews are enabled in the room list.
|
||||||
*/
|
*/
|
||||||
isMessagePreviewEnabled: boolean;
|
isMessagePreviewEnabled: boolean;
|
||||||
/**
|
|
||||||
* Whether the user can create sections in the room list.
|
|
||||||
*/
|
|
||||||
canCreateSection: boolean;
|
|
||||||
/**
|
|
||||||
* Whether to use the compose icon instead of the create icon.
|
|
||||||
*/
|
|
||||||
useComposeIcon: boolean;
|
|
||||||
/**
|
/**
|
||||||
* If "collapse", an icon to collapse all sections is shown.
|
* If "collapse", an icon to collapse all sections is shown.
|
||||||
* If "expand", an icon to expand all sections is shown.
|
* If "expand", an icon to expand all sections is shown.
|
||||||
@@ -160,7 +145,7 @@ interface RoomListHeaderViewProps {
|
|||||||
*/
|
*/
|
||||||
export function RoomListHeaderView({ vm }: Readonly<RoomListHeaderViewProps>): JSX.Element {
|
export function RoomListHeaderView({ vm }: Readonly<RoomListHeaderViewProps>): JSX.Element {
|
||||||
const { translate: _t } = useI18n();
|
const { translate: _t } = useI18n();
|
||||||
const { title, displaySpaceMenu, displayComposeMenu, useComposeIcon, collapseSections } = useViewModel(vm);
|
const { title, displaySpaceMenu, collapseSections } = useViewModel(vm);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
@@ -197,24 +182,7 @@ export function RoomListHeaderView({ vm }: Readonly<RoomListHeaderViewProps>): J
|
|||||||
)}
|
)}
|
||||||
</IconButton>
|
</IconButton>
|
||||||
)}
|
)}
|
||||||
|
<ComposeMenuView vm={vm} />
|
||||||
{/* If we don't display the compose menu, it means that the user can only send DM */}
|
|
||||||
{displayComposeMenu ? (
|
|
||||||
<ComposeMenuView vm={vm} />
|
|
||||||
) : (
|
|
||||||
<IconButton
|
|
||||||
size="28px"
|
|
||||||
style={{ padding: "4px" }}
|
|
||||||
onClick={(e) => vm.createChatRoom(e.nativeEvent)}
|
|
||||||
tooltip={_t("action|new_conversation")}
|
|
||||||
>
|
|
||||||
{useComposeIcon ? (
|
|
||||||
<ComposeIcon color="var(--cpd-color-icon-secondary)" aria-hidden />
|
|
||||||
) : (
|
|
||||||
<PlusIcon color="var(--cpd-color-icon-secondary)" aria-hidden />
|
|
||||||
)}
|
|
||||||
</IconButton>
|
|
||||||
)}
|
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|||||||
@@ -145,12 +145,7 @@ exports[`RoomListHeaderView > renders collapse button 1`] = `
|
|||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
clip-rule="evenodd"
|
d="M11 13H6a.97.97 0 0 1-.713-.287A.97.97 0 0 1 5 12q0-.424.287-.713A.97.97 0 0 1 6 11h5V6q0-.424.287-.713A.97.97 0 0 1 12 5q.424 0 .713.287Q13 5.576 13 6v5h5q.424 0 .712.287.288.288.288.713 0 .424-.288.713A.97.97 0 0 1 18 13h-5v5q0 .424-.287.712A.97.97 0 0 1 12 19a.97.97 0 0 1-.713-.288A.97.97 0 0 1 11 18z"
|
||||||
d="M16.937 2.82a2 2 0 0 1 2.828 0l1.415 1.414a2 2 0 0 1 0 2.829l-7.071 7.07c-.195.196-.42.342-.66.44a1 1 0 0 1-.168.072l-3.993 1.331a1 1 0 0 1-1.265-1.265l1.331-3.992q.03-.09.073-.168m10.338-4.903-6.717 6.718-1.414-1.414 6.717-6.718z"
|
|
||||||
fill-rule="evenodd"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M3 5a2 2 0 0 1 2-2h6a1 1 0 1 1 0 2H5v14h14v-6a1 1 0 1 1 2 0v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"
|
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
@@ -306,12 +301,7 @@ exports[`RoomListHeaderView > renders expand button 1`] = `
|
|||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
clip-rule="evenodd"
|
d="M11 13H6a.97.97 0 0 1-.713-.287A.97.97 0 0 1 5 12q0-.424.287-.713A.97.97 0 0 1 6 11h5V6q0-.424.287-.713A.97.97 0 0 1 12 5q.424 0 .713.287Q13 5.576 13 6v5h5q.424 0 .712.287.288.288.288.713 0 .424-.288.713A.97.97 0 0 1 18 13h-5v5q0 .424-.287.712A.97.97 0 0 1 12 19a.97.97 0 0 1-.713-.288A.97.97 0 0 1 11 18z"
|
||||||
d="M16.937 2.82a2 2 0 0 1 2.828 0l1.415 1.414a2 2 0 0 1 0 2.829l-7.071 7.07c-.195.196-.42.342-.66.44a1 1 0 0 1-.168.072l-3.993 1.331a1 1 0 0 1-1.265-1.265l1.331-3.992q.03-.09.073-.168m10.338-4.903-6.717 6.718-1.414-1.414 6.717-6.718z"
|
|
||||||
fill-rule="evenodd"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M3 5a2 2 0 0 1 2-2h6a1 1 0 1 1 0 2H5v14h14v-6a1 1 0 1 1 2 0v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"
|
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
@@ -440,140 +430,7 @@ exports[`RoomListHeaderView > renders the default state 1`] = `
|
|||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
clip-rule="evenodd"
|
d="M11 13H6a.97.97 0 0 1-.713-.287A.97.97 0 0 1 5 12q0-.424.287-.713A.97.97 0 0 1 6 11h5V6q0-.424.287-.713A.97.97 0 0 1 12 5q.424 0 .713.287Q13 5.576 13 6v5h5q.424 0 .712.287.288.288.288.713 0 .424-.288.713A.97.97 0 0 1 18 13h-5v5q0 .424-.287.712A.97.97 0 0 1 12 19a.97.97 0 0 1-.713-.288A.97.97 0 0 1 11 18z"
|
||||||
d="M16.937 2.82a2 2 0 0 1 2.828 0l1.415 1.414a2 2 0 0 1 0 2.829l-7.071 7.07c-.195.196-.42.342-.66.44a1 1 0 0 1-.168.072l-3.993 1.331a1 1 0 0 1-1.265-1.265l1.331-3.992q.03-.09.073-.168m10.338-4.903-6.717 6.718-1.414-1.414 6.717-6.718z"
|
|
||||||
fill-rule="evenodd"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M3 5a2 2 0 0 1 2-2h6a1 1 0 1 1 0 2H5v14h14v-6a1 1 0 1 1 2 0v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`RoomListHeaderView > renders without compose menu 1`] = `
|
|
||||||
<div>
|
|
||||||
<header
|
|
||||||
aria-label="Room options"
|
|
||||||
class="Flex-module_flex RoomListHeaderView-module_header"
|
|
||||||
data-testid="room-list-header"
|
|
||||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: end; --mx-flex-justify: start; --mx-flex-gap: 0; --mx-flex-wrap: nowrap;"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="Flex-module_flex RoomListHeaderView-module_container"
|
|
||||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: space-between; --mx-flex-gap: var(--cpd-space-3x); --mx-flex-wrap: nowrap;"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="Flex-module_flex RoomListHeaderView-module_title"
|
|
||||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-1x); --mx-flex-wrap: nowrap;"
|
|
||||||
>
|
|
||||||
<h1
|
|
||||||
class="_typography_6v6n8_153 _font-heading-sm-semibold_6v6n8_93"
|
|
||||||
title="Rooms"
|
|
||||||
>
|
|
||||||
Rooms
|
|
||||||
</h1>
|
|
||||||
<button
|
|
||||||
aria-disabled="false"
|
|
||||||
aria-expanded="false"
|
|
||||||
aria-haspopup="menu"
|
|
||||||
aria-label="Open space menu"
|
|
||||||
class="_icon-button_1215g_8 SpaceMenuView-module_button"
|
|
||||||
data-kind="primary"
|
|
||||||
data-state="closed"
|
|
||||||
id="radix-react-use-id-1"
|
|
||||||
role="button"
|
|
||||||
style="--cpd-icon-button-size: 24px; padding: 2px;"
|
|
||||||
tabindex="0"
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="_indicator-icon_147l5_17"
|
|
||||||
style="--cpd-icon-button-size: 100%;"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
fill="currentColor"
|
|
||||||
height="1em"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
width="1em"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M12 14.95q-.2 0-.375-.062a.9.9 0 0 1-.325-.213l-4.6-4.6a.95.95 0 0 1-.275-.7q0-.425.275-.7a.95.95 0 0 1 .7-.275q.425 0 .7.275l3.9 3.9 3.9-3.9a.95.95 0 0 1 .7-.275q.425 0 .7.275a.95.95 0 0 1 .275.7.95.95 0 0 1-.275.7l-4.6 4.6q-.15.15-.325.212a1.1 1.1 0 0 1-.375.063"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="Flex-module_flex"
|
|
||||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-2x); --mx-flex-wrap: nowrap;"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
aria-disabled="false"
|
|
||||||
aria-expanded="false"
|
|
||||||
aria-haspopup="menu"
|
|
||||||
aria-label="Room Options"
|
|
||||||
aria-labelledby="react-use-id-2"
|
|
||||||
class="_icon-button_1215g_8"
|
|
||||||
data-kind="primary"
|
|
||||||
data-state="closed"
|
|
||||||
id="radix-react-use-id-3"
|
|
||||||
role="button"
|
|
||||||
style="--cpd-icon-button-size: 28px; padding: 4px;"
|
|
||||||
tabindex="0"
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="_indicator-icon_147l5_17"
|
|
||||||
style="--cpd-icon-button-size: 100%;"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
fill="currentColor"
|
|
||||||
height="1em"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
width="1em"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M6 14q-.824 0-1.412-.588A1.93 1.93 0 0 1 4 12q0-.825.588-1.412A1.93 1.93 0 0 1 6 10q.824 0 1.412.588Q8 11.175 8 12t-.588 1.412A1.93 1.93 0 0 1 6 14m6 0q-.825 0-1.412-.588A1.93 1.93 0 0 1 10 12q0-.825.588-1.412A1.93 1.93 0 0 1 12 10q.825 0 1.412.588Q14 11.175 14 12t-.588 1.412A1.93 1.93 0 0 1 12 14m6 0q-.824 0-1.413-.588A1.93 1.93 0 0 1 16 12q0-.825.587-1.412A1.93 1.93 0 0 1 18 10q.824 0 1.413.588Q20 11.175 20 12t-.587 1.412A1.93 1.93 0 0 1 18 14"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
aria-labelledby="react-use-id-4"
|
|
||||||
class="_icon-button_1215g_8"
|
|
||||||
data-kind="primary"
|
|
||||||
role="button"
|
|
||||||
style="--cpd-icon-button-size: 28px; padding: 4px;"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="_indicator-icon_147l5_17"
|
|
||||||
style="--cpd-icon-button-size: 100%;"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
aria-hidden="true"
|
|
||||||
color="var(--cpd-color-icon-secondary)"
|
|
||||||
fill="currentColor"
|
|
||||||
height="1em"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
width="1em"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
clip-rule="evenodd"
|
|
||||||
d="M16.937 2.82a2 2 0 0 1 2.828 0l1.415 1.414a2 2 0 0 1 0 2.829l-7.071 7.07c-.195.196-.42.342-.66.44a1 1 0 0 1-.168.072l-3.993 1.331a1 1 0 0 1-1.265-1.265l1.331-3.992q.03-.09.073-.168m10.338-4.903-6.717 6.718-1.414-1.414 6.717-6.718z"
|
|
||||||
fill-rule="evenodd"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M3 5a2 2 0 0 1 2-2h6a1 1 0 1 1 0 2H5v14h14v-6a1 1 0 1 1 2 0v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"
|
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
@@ -671,12 +528,7 @@ exports[`RoomListHeaderView > renders without space menu 1`] = `
|
|||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
clip-rule="evenodd"
|
d="M11 13H6a.97.97 0 0 1-.713-.287A.97.97 0 0 1 5 12q0-.424.287-.713A.97.97 0 0 1 6 11h5V6q0-.424.287-.713A.97.97 0 0 1 12 5q.424 0 .713.287Q13 5.576 13 6v5h5q.424 0 .712.287.288.288.288.713 0 .424-.288.713A.97.97 0 0 1 18 13h-5v5q0 .424-.287.712A.97.97 0 0 1 12 19a.97.97 0 0 1-.713-.288A.97.97 0 0 1 11 18z"
|
||||||
d="M16.937 2.82a2 2 0 0 1 2.828 0l1.415 1.414a2 2 0 0 1 0 2.829l-7.071 7.07c-.195.196-.42.342-.66.44a1 1 0 0 1-.168.072l-3.993 1.331a1 1 0 0 1-1.265-1.265l1.331-3.992q.03-.09.073-.168m10.338-4.903-6.717 6.718-1.414-1.414 6.717-6.718z"
|
|
||||||
fill-rule="evenodd"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M3 5a2 2 0 0 1 2-2h6a1 1 0 1 1 0 2H5v14h14v-6a1 1 0 1 1 2 0v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"
|
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import { type RoomListHeaderViewSnapshot } from "./RoomListHeaderView";
|
|||||||
|
|
||||||
export const defaultSnapshot: RoomListHeaderViewSnapshot = {
|
export const defaultSnapshot: RoomListHeaderViewSnapshot = {
|
||||||
title: "Rooms",
|
title: "Rooms",
|
||||||
displayComposeMenu: true,
|
|
||||||
displaySpaceMenu: true,
|
displaySpaceMenu: true,
|
||||||
canCreateRoom: true,
|
canCreateRoom: true,
|
||||||
canCreateVideoRoom: true,
|
canCreateVideoRoom: true,
|
||||||
@@ -17,7 +16,5 @@ export const defaultSnapshot: RoomListHeaderViewSnapshot = {
|
|||||||
canAccessSpaceSettings: true,
|
canAccessSpaceSettings: true,
|
||||||
activeSortOption: "recent",
|
activeSortOption: "recent",
|
||||||
isMessagePreviewEnabled: true,
|
isMessagePreviewEnabled: true,
|
||||||
useComposeIcon: true,
|
|
||||||
canCreateSection: true,
|
|
||||||
displaySectionReleaseAnnouncement: false,
|
displaySectionReleaseAnnouncement: false,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
import React, { useState, type JSX } from "react";
|
import React, { useState, type JSX } from "react";
|
||||||
import { IconButton, Menu, MenuItem, ReleaseAnnouncement } from "@vector-im/compound-web";
|
import { IconButton, Menu, MenuItem, ReleaseAnnouncement } from "@vector-im/compound-web";
|
||||||
import ComposeIcon from "@vector-im/compound-design-tokens/assets/web/icons/compose";
|
|
||||||
import VideoCallIcon from "@vector-im/compound-design-tokens/assets/web/icons/video-call";
|
import VideoCallIcon from "@vector-im/compound-design-tokens/assets/web/icons/video-call";
|
||||||
import ChatIcon from "@vector-im/compound-design-tokens/assets/web/icons/chat";
|
import ChatIcon from "@vector-im/compound-design-tokens/assets/web/icons/chat";
|
||||||
import RoomIcon from "@vector-im/compound-design-tokens/assets/web/icons/room";
|
import RoomIcon from "@vector-im/compound-design-tokens/assets/web/icons/room";
|
||||||
@@ -37,17 +36,12 @@ interface ComposeMenuViewProps {
|
|||||||
export function ComposeMenuView({ vm }: ComposeMenuViewProps): JSX.Element {
|
export function ComposeMenuView({ vm }: ComposeMenuViewProps): JSX.Element {
|
||||||
const { translate: _t } = useI18n();
|
const { translate: _t } = useI18n();
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const { canCreateRoom, canCreateVideoRoom, canCreateSection, useComposeIcon, displaySectionReleaseAnnouncement } =
|
const { canCreateRoom, canCreateVideoRoom, displaySectionReleaseAnnouncement } = useViewModel(vm);
|
||||||
useViewModel(vm);
|
|
||||||
|
|
||||||
// 28px button with a 20px icon
|
// 28px button with a 20px icon
|
||||||
const button = (
|
const button = (
|
||||||
<IconButton size="28px" style={{ padding: "4px" }} tooltip={_t("action|new_conversation")}>
|
<IconButton size="28px" style={{ padding: "4px" }} tooltip={_t("action|new_conversation")}>
|
||||||
{useComposeIcon ? (
|
<PlusIcon color="var(--cpd-color-icon-secondary)" aria-hidden />
|
||||||
<ComposeIcon color="var(--cpd-color-icon-secondary)" aria-hidden />
|
|
||||||
) : (
|
|
||||||
<PlusIcon color="var(--cpd-color-icon-secondary)" aria-hidden />
|
|
||||||
)}
|
|
||||||
</IconButton>
|
</IconButton>
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -86,9 +80,7 @@ export function ComposeMenuView({ vm }: ComposeMenuViewProps): JSX.Element {
|
|||||||
hideChevron
|
hideChevron
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{canCreateSection && (
|
<MenuItem Icon={SectionIcon} label={_t("action|new_section")} onSelect={vm.createSection} hideChevron />
|
||||||
<MenuItem Icon={SectionIcon} label={_t("action|new_section")} onSelect={vm.createSection} hideChevron />
|
|
||||||
)}
|
|
||||||
</Menu>
|
</Menu>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,12 +30,7 @@ exports[`<ComposeMenuView /> > should match snapshot 1`] = `
|
|||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
clip-rule="evenodd"
|
d="M11 13H6a.97.97 0 0 1-.713-.287A.97.97 0 0 1 5 12q0-.424.287-.713A.97.97 0 0 1 6 11h5V6q0-.424.287-.713A.97.97 0 0 1 12 5q.424 0 .713.287Q13 5.576 13 6v5h5q.424 0 .712.287.288.288.288.713 0 .424-.288.713A.97.97 0 0 1 18 13h-5v5q0 .424-.287.712A.97.97 0 0 1 12 19a.97.97 0 0 1-.713-.288A.97.97 0 0 1 11 18z"
|
||||||
d="M16.937 2.82a2 2 0 0 1 2.828 0l1.415 1.414a2 2 0 0 1 0 2.829l-7.071 7.07c-.195.196-.42.342-.66.44a1 1 0 0 1-.168.072l-3.993 1.331a1 1 0 0 1-1.265-1.265l1.331-3.992q.03-.09.073-.168m10.338-4.903-6.717 6.718-1.414-1.414 6.717-6.718z"
|
|
||||||
fill-rule="evenodd"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M3 5a2 2 0 0 1 2-2h6a1 1 0 1 1 0 2H5v14h14v-6a1 1 0 1 1 2 0v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"
|
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export default meta;
|
|||||||
type Story = StoryObj<typeof meta>;
|
type Story = StoryObj<typeof meta>;
|
||||||
|
|
||||||
// All available filter IDs
|
// All available filter IDs
|
||||||
const allFilterIds: FilterId[] = ["unread", "people", "rooms", "favourite", "mentions", "invites", "low_priority"];
|
const allFilterIds: FilterId[] = ["unread", "people", "rooms", "mentions", "invites"];
|
||||||
|
|
||||||
// Subset of filters for narrow container tests
|
// Subset of filters for narrow container tests
|
||||||
const fewFilterIds: FilterId[] = ["people", "rooms", "unread"];
|
const fewFilterIds: FilterId[] = ["people", "rooms", "unread"];
|
||||||
|
|||||||
@@ -26,14 +26,10 @@ const filterIdToLabel = (filterId: FilterId): string => {
|
|||||||
return _t("room_list|filters|people");
|
return _t("room_list|filters|people");
|
||||||
case "rooms":
|
case "rooms":
|
||||||
return _t("room_list|filters|rooms");
|
return _t("room_list|filters|rooms");
|
||||||
case "favourite":
|
|
||||||
return _t("room_list|filters|favourite");
|
|
||||||
case "mentions":
|
case "mentions":
|
||||||
return _t("room_list|filters|mentions");
|
return _t("room_list|filters|mentions");
|
||||||
case "invites":
|
case "invites":
|
||||||
return _t("room_list|filters|invites");
|
return _t("room_list|filters|invites");
|
||||||
case "low_priority":
|
|
||||||
return _t("room_list|filters|low_priority");
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -7,33 +7,6 @@ exports[`<RoomListPrimaryFilters /> stories > snapshots > renders Default story
|
|||||||
data-testid="primary-filters"
|
data-testid="primary-filters"
|
||||||
style="--mx-flex-display: flex; --mx-flex-direction: row-reverse; --mx-flex-align: start; --mx-flex-justify: space-between; --mx-flex-gap: var(--cpd-space-3x); --mx-flex-wrap: nowrap;"
|
style="--mx-flex-display: flex; --mx-flex-direction: row-reverse; --mx-flex-align: start; --mx-flex-justify: space-between; --mx-flex-gap: var(--cpd-space-3x); --mx-flex-wrap: nowrap;"
|
||||||
>
|
>
|
||||||
<button
|
|
||||||
aria-controls="react-use-id-1"
|
|
||||||
aria-expanded="false"
|
|
||||||
aria-label="Expand filter list"
|
|
||||||
class="_icon-button_1215g_8 RoomListPrimaryFilters-module_iconButton"
|
|
||||||
data-kind="secondary"
|
|
||||||
role="button"
|
|
||||||
style="--cpd-icon-button-size: 28px;"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="_indicator-icon_147l5_17"
|
|
||||||
style="--cpd-icon-button-size: 100%;"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
fill="currentColor"
|
|
||||||
height="1em"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
width="1em"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M12 14.95q-.2 0-.375-.062a.9.9 0 0 1-.325-.213l-4.6-4.6a.95.95 0 0 1-.275-.7q0-.425.275-.7a.95.95 0 0 1 .7-.275q.425 0 .7.275l3.9 3.9 3.9-3.9a.95.95 0 0 1 .7-.275q.425 0 .7.275a.95.95 0 0 1 .275.7.95.95 0 0 1-.275.7l-4.6 4.6q-.15.15-.325.212a1.1 1.1 0 0 1-.375.063"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
<div
|
<div
|
||||||
aria-label="Room list filters"
|
aria-label="Room list filters"
|
||||||
class="Flex-module_flex RoomListPrimaryFilters-module_list"
|
class="Flex-module_flex RoomListPrimaryFilters-module_list"
|
||||||
@@ -68,15 +41,6 @@ exports[`<RoomListPrimaryFilters /> stories > snapshots > renders Default story
|
|||||||
>
|
>
|
||||||
Rooms
|
Rooms
|
||||||
</button>
|
</button>
|
||||||
<button
|
|
||||||
aria-hidden="false"
|
|
||||||
aria-selected="false"
|
|
||||||
class="_chat-filter_5qdp0_8"
|
|
||||||
role="option"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
Favourites
|
|
||||||
</button>
|
|
||||||
<button
|
<button
|
||||||
aria-hidden="false"
|
aria-hidden="false"
|
||||||
aria-selected="false"
|
aria-selected="false"
|
||||||
@@ -95,15 +59,6 @@ exports[`<RoomListPrimaryFilters /> stories > snapshots > renders Default story
|
|||||||
>
|
>
|
||||||
Invites
|
Invites
|
||||||
</button>
|
</button>
|
||||||
<button
|
|
||||||
aria-hidden="true"
|
|
||||||
aria-selected="false"
|
|
||||||
class="_chat-filter_5qdp0_8 wrapping"
|
|
||||||
role="option"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
Low priority
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -285,33 +240,6 @@ exports[`<RoomListPrimaryFilters /> stories > snapshots > renders PeopleSelected
|
|||||||
data-testid="primary-filters"
|
data-testid="primary-filters"
|
||||||
style="--mx-flex-display: flex; --mx-flex-direction: row-reverse; --mx-flex-align: start; --mx-flex-justify: space-between; --mx-flex-gap: var(--cpd-space-3x); --mx-flex-wrap: nowrap;"
|
style="--mx-flex-display: flex; --mx-flex-direction: row-reverse; --mx-flex-align: start; --mx-flex-justify: space-between; --mx-flex-gap: var(--cpd-space-3x); --mx-flex-wrap: nowrap;"
|
||||||
>
|
>
|
||||||
<button
|
|
||||||
aria-controls="react-use-id-1"
|
|
||||||
aria-expanded="false"
|
|
||||||
aria-label="Expand filter list"
|
|
||||||
class="_icon-button_1215g_8 RoomListPrimaryFilters-module_iconButton"
|
|
||||||
data-kind="secondary"
|
|
||||||
role="button"
|
|
||||||
style="--cpd-icon-button-size: 28px;"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="_indicator-icon_147l5_17"
|
|
||||||
style="--cpd-icon-button-size: 100%;"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
fill="currentColor"
|
|
||||||
height="1em"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
width="1em"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M12 14.95q-.2 0-.375-.062a.9.9 0 0 1-.325-.213l-4.6-4.6a.95.95 0 0 1-.275-.7q0-.425.275-.7a.95.95 0 0 1 .7-.275q.425 0 .7.275l3.9 3.9 3.9-3.9a.95.95 0 0 1 .7-.275q.425 0 .7.275a.95.95 0 0 1 .275.7.95.95 0 0 1-.275.7l-4.6 4.6q-.15.15-.325.212a1.1 1.1 0 0 1-.375.063"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
<div
|
<div
|
||||||
aria-label="Room list filters"
|
aria-label="Room list filters"
|
||||||
class="Flex-module_flex RoomListPrimaryFilters-module_list"
|
class="Flex-module_flex RoomListPrimaryFilters-module_list"
|
||||||
@@ -346,15 +274,6 @@ exports[`<RoomListPrimaryFilters /> stories > snapshots > renders PeopleSelected
|
|||||||
>
|
>
|
||||||
Rooms
|
Rooms
|
||||||
</button>
|
</button>
|
||||||
<button
|
|
||||||
aria-hidden="false"
|
|
||||||
aria-selected="false"
|
|
||||||
class="_chat-filter_5qdp0_8"
|
|
||||||
role="option"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
Favourites
|
|
||||||
</button>
|
|
||||||
<button
|
<button
|
||||||
aria-hidden="false"
|
aria-hidden="false"
|
||||||
aria-selected="false"
|
aria-selected="false"
|
||||||
@@ -373,15 +292,6 @@ exports[`<RoomListPrimaryFilters /> stories > snapshots > renders PeopleSelected
|
|||||||
>
|
>
|
||||||
Invites
|
Invites
|
||||||
</button>
|
</button>
|
||||||
<button
|
|
||||||
aria-hidden="true"
|
|
||||||
aria-selected="false"
|
|
||||||
class="_chat-filter_5qdp0_8 wrapping"
|
|
||||||
role="option"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
Low priority
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { useEffect, useState } from "react";
|
|||||||
* Standard filter identifiers that can be used across implementations.
|
* Standard filter identifiers that can be used across implementations.
|
||||||
* These are stable keys - the view layer maps them to translated labels.
|
* These are stable keys - the view layer maps them to translated labels.
|
||||||
*/
|
*/
|
||||||
export type FilterId = "unread" | "people" | "rooms" | "favourite" | "mentions" | "invites" | "low_priority";
|
export type FilterId = "unread" | "people" | "rooms" | "mentions" | "invites";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A hook to sort the filter IDs by active state.
|
* A hook to sort the filter IDs by active state.
|
||||||
|
|||||||
@@ -64,13 +64,6 @@ export const RoomListEmptyStateView: React.FC<RoomListEmptyStateViewProps> = ({
|
|||||||
|
|
||||||
// Handle different filter cases based on filter ID
|
// Handle different filter cases based on filter ID
|
||||||
switch (snapshot.activeFilterId) {
|
switch (snapshot.activeFilterId) {
|
||||||
case "favourite":
|
|
||||||
return (
|
|
||||||
<GenericPlaceholder
|
|
||||||
title={_t("room_list|empty|no_favourites")}
|
|
||||||
description={_t("room_list|empty|no_favourites_description")}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
case "people":
|
case "people":
|
||||||
return (
|
return (
|
||||||
<GenericPlaceholder
|
<GenericPlaceholder
|
||||||
@@ -109,14 +102,6 @@ export const RoomListEmptyStateView: React.FC<RoomListEmptyStateViewProps> = ({
|
|||||||
onAction={() => vm.onToggleFilter(snapshot.activeFilterId!)}
|
onAction={() => vm.onToggleFilter(snapshot.activeFilterId!)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
case "low_priority":
|
|
||||||
return (
|
|
||||||
<ActionPlaceholder
|
|
||||||
title={_t("room_list|empty|no_lowpriority")}
|
|
||||||
action={_t("room_list|empty|show_activity")}
|
|
||||||
onAction={() => vm.onToggleFilter(snapshot.activeFilterId!)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
default:
|
default:
|
||||||
return (
|
return (
|
||||||
<GenericPlaceholder
|
<GenericPlaceholder
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ import {
|
|||||||
type RoomListViewProps = RoomListViewSnapshot &
|
type RoomListViewProps = RoomListViewSnapshot &
|
||||||
RoomListViewActions & { renderAvatar: (room: Room) => React.ReactElement };
|
RoomListViewActions & { renderAvatar: (room: Room) => React.ReactElement };
|
||||||
|
|
||||||
const mockFilterIds: FilterId[] = ["unread", "people", "rooms", "favourite"];
|
const mockFilterIds: FilterId[] = ["unread", "people", "rooms"];
|
||||||
|
|
||||||
// Wrapper component that creates a mocked ViewModel
|
// Wrapper component that creates a mocked ViewModel
|
||||||
const RoomListViewWrapperImpl = ({
|
const RoomListViewWrapperImpl = ({
|
||||||
@@ -164,12 +164,12 @@ export const EmptyWithoutCreatePermission: Story = {
|
|||||||
|
|
||||||
export const WithActiveFilter: Story = {
|
export const WithActiveFilter: Story = {
|
||||||
args: {
|
args: {
|
||||||
filterIds: ["unread", "people", "rooms", "favourite"],
|
filterIds: ["unread", "people", "rooms"],
|
||||||
activeFilterId: "favourite",
|
activeFilterId: "people",
|
||||||
roomListState: {
|
roomListState: {
|
||||||
activeRoomIndex: undefined,
|
activeRoomIndex: undefined,
|
||||||
spaceId: "!space:server",
|
spaceId: "!space:server",
|
||||||
filterKeys: ["favourites"],
|
filterKeys: ["people"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -184,14 +184,6 @@ export const WithSelection: Story = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const EmptyFavouriteFilter: Story = {
|
|
||||||
args: {
|
|
||||||
isRoomListEmpty: true,
|
|
||||||
filterIds: ["favourite", "people"],
|
|
||||||
activeFilterId: "favourite",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export const EmptyPeopleFilter: Story = {
|
export const EmptyPeopleFilter: Story = {
|
||||||
args: {
|
args: {
|
||||||
isRoomListEmpty: true,
|
isRoomListEmpty: true,
|
||||||
@@ -233,14 +225,6 @@ export const EmptyMentionsFilter: Story = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const EmptyLowPriorityFilter: Story = {
|
|
||||||
args: {
|
|
||||||
isRoomListEmpty: true,
|
|
||||||
filterIds: ["low_priority", "people"],
|
|
||||||
activeFilterId: "low_priority",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export const SmallFlatList: Story = {
|
export const SmallFlatList: Story = {
|
||||||
args: {
|
args: {
|
||||||
sections: mockSmallListSections,
|
sections: mockSmallListSections,
|
||||||
|
|||||||
@@ -30,13 +30,11 @@ const {
|
|||||||
LargeFlatList,
|
LargeFlatList,
|
||||||
SmallSectionList,
|
SmallSectionList,
|
||||||
LargeSectionList,
|
LargeSectionList,
|
||||||
EmptyFavouriteFilter,
|
|
||||||
EmptyPeopleFilter,
|
EmptyPeopleFilter,
|
||||||
EmptyRoomsFilter,
|
EmptyRoomsFilter,
|
||||||
EmptyUnreadFilter,
|
EmptyUnreadFilter,
|
||||||
EmptyInvitesFilter,
|
EmptyInvitesFilter,
|
||||||
EmptyMentionsFilter,
|
EmptyMentionsFilter,
|
||||||
EmptyLowPriorityFilter,
|
|
||||||
Toast,
|
Toast,
|
||||||
} = composeStories(stories);
|
} = composeStories(stories);
|
||||||
|
|
||||||
@@ -96,11 +94,6 @@ describe("<RoomListView />", () => {
|
|||||||
expect(container).toMatchSnapshot();
|
expect(container).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("renders EmptyFavouriteFilter story", () => {
|
|
||||||
const { container } = renderWithMockContext(<EmptyFavouriteFilter />);
|
|
||||||
expect(container).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("renders EmptyPeopleFilter story", () => {
|
it("renders EmptyPeopleFilter story", () => {
|
||||||
const { container } = renderWithMockContext(<EmptyPeopleFilter />);
|
const { container } = renderWithMockContext(<EmptyPeopleFilter />);
|
||||||
expect(container).toMatchSnapshot();
|
expect(container).toMatchSnapshot();
|
||||||
@@ -126,11 +119,6 @@ describe("<RoomListView />", () => {
|
|||||||
expect(container).toMatchSnapshot();
|
expect(container).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("renders EmptyLowPriorityFilter story", () => {
|
|
||||||
const { container } = renderWithMockContext(<EmptyLowPriorityFilter />);
|
|
||||||
expect(container).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("renders Toast story", () => {
|
it("renders Toast story", () => {
|
||||||
const { container } = renderWithMockContext(<Toast />);
|
const { container } = renderWithMockContext(<Toast />);
|
||||||
expect(container).toMatchSnapshot();
|
expect(container).toMatchSnapshot();
|
||||||
@@ -190,21 +178,12 @@ describe("<RoomListView />", () => {
|
|||||||
expect(EmptyMentionsFilter.args.onToggleFilter).toHaveBeenCalled();
|
expect(EmptyMentionsFilter.args.onToggleFilter).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should call onToggleFilter when See all activity is clicked in low priority empty state", async () => {
|
|
||||||
const user = userEvent.setup();
|
|
||||||
renderWithMockContext(<EmptyLowPriorityFilter />);
|
|
||||||
|
|
||||||
await user.click(screen.getByRole("button", { name: "See all activity" }));
|
|
||||||
|
|
||||||
expect(EmptyLowPriorityFilter.args.onToggleFilter).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should call closeToast when close button is clicked on toast", async () => {
|
it("should call closeToast when close button is clicked on toast", async () => {
|
||||||
const user = userEvent.setup();
|
const user = userEvent.setup();
|
||||||
renderWithMockContext(<Toast />);
|
renderWithMockContext(<Toast />);
|
||||||
|
|
||||||
await user.click(screen.getByRole("button", { name: "Close" }));
|
await user.click(screen.getByRole("button", { name: "Close" }));
|
||||||
|
|
||||||
expect(EmptyLowPriorityFilter.args.closeToast).toHaveBeenCalled();
|
expect(Toast.args.closeToast).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -45,15 +45,6 @@ exports[`<RoomListView /> > renders Default story 1`] = `
|
|||||||
>
|
>
|
||||||
Rooms
|
Rooms
|
||||||
</button>
|
</button>
|
||||||
<button
|
|
||||||
aria-hidden="false"
|
|
||||||
aria-selected="false"
|
|
||||||
class="_chat-filter_5qdp0_8"
|
|
||||||
role="option"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
Favourites
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -2726,15 +2717,6 @@ exports[`<RoomListView /> > renders Empty story 1`] = `
|
|||||||
>
|
>
|
||||||
Rooms
|
Rooms
|
||||||
</button>
|
</button>
|
||||||
<button
|
|
||||||
aria-hidden="false"
|
|
||||||
aria-selected="false"
|
|
||||||
class="_chat-filter_5qdp0_8"
|
|
||||||
role="option"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
Favourites
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -2815,75 +2797,6 @@ exports[`<RoomListView /> > renders Empty story 1`] = `
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`<RoomListView /> > renders EmptyFavouriteFilter story 1`] = `
|
|
||||||
<div>
|
|
||||||
<div
|
|
||||||
style="width: 320px; height: 600px; border: 1px solid var(--cpd-color-border-interactive-primary); display: flex; flex-direction: column; resize: horizontal; overflow: auto; min-width: 250px; max-width: 800px;"
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<div
|
|
||||||
class="Flex-module_flex RoomListPrimaryFilters-module_roomListPrimaryFilters"
|
|
||||||
data-testid="primary-filters"
|
|
||||||
style="--mx-flex-display: flex; --mx-flex-direction: row-reverse; --mx-flex-align: start; --mx-flex-justify: space-between; --mx-flex-gap: var(--cpd-space-3x); --mx-flex-wrap: nowrap;"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
aria-label="Room list filters"
|
|
||||||
class="Flex-module_flex RoomListPrimaryFilters-module_list"
|
|
||||||
id="react-use-id-1"
|
|
||||||
role="listbox"
|
|
||||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-2x); --mx-flex-wrap: wrap;"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
aria-hidden="false"
|
|
||||||
aria-selected="true"
|
|
||||||
class="_chat-filter_5qdp0_8"
|
|
||||||
role="option"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
Favourites
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
aria-hidden="false"
|
|
||||||
aria-selected="false"
|
|
||||||
class="_chat-filter_5qdp0_8"
|
|
||||||
role="option"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
People
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="Flex-module_flex RoomListView-module_list"
|
|
||||||
style="--mx-flex-display: flex; --mx-flex-direction: column; --mx-flex-align: start; --mx-flex-justify: start; --mx-flex-gap: 0; --mx-flex-wrap: nowrap;"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="AutoHideScrollbar-module_scrollbar RoomListView-module_scrollbar"
|
|
||||||
tabindex="-1"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="Flex-module_flex RoomListEmptyStateView-module_genericPlaceholder"
|
|
||||||
data-testid="empty-room-list"
|
|
||||||
style="--mx-flex-display: flex; --mx-flex-direction: column; --mx-flex-align: stretch; --mx-flex-justify: center; --mx-flex-gap: var(--cpd-space-2x); --mx-flex-wrap: nowrap;"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="RoomListEmptyStateView-module_title"
|
|
||||||
>
|
|
||||||
You don't have favourite chats yet
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
class="RoomListEmptyStateView-module_description"
|
|
||||||
>
|
|
||||||
You can add a chat to your favourites in the chat settings
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`<RoomListView /> > renders EmptyInvitesFilter story 1`] = `
|
exports[`<RoomListView /> > renders EmptyInvitesFilter story 1`] = `
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
@@ -2957,79 +2870,6 @@ exports[`<RoomListView /> > renders EmptyInvitesFilter story 1`] = `
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`<RoomListView /> > renders EmptyLowPriorityFilter story 1`] = `
|
|
||||||
<div>
|
|
||||||
<div
|
|
||||||
style="width: 320px; height: 600px; border: 1px solid var(--cpd-color-border-interactive-primary); display: flex; flex-direction: column; resize: horizontal; overflow: auto; min-width: 250px; max-width: 800px;"
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<div
|
|
||||||
class="Flex-module_flex RoomListPrimaryFilters-module_roomListPrimaryFilters"
|
|
||||||
data-testid="primary-filters"
|
|
||||||
style="--mx-flex-display: flex; --mx-flex-direction: row-reverse; --mx-flex-align: start; --mx-flex-justify: space-between; --mx-flex-gap: var(--cpd-space-3x); --mx-flex-wrap: nowrap;"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
aria-label="Room list filters"
|
|
||||||
class="Flex-module_flex RoomListPrimaryFilters-module_list"
|
|
||||||
id="react-use-id-1"
|
|
||||||
role="listbox"
|
|
||||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-2x); --mx-flex-wrap: wrap;"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
aria-hidden="false"
|
|
||||||
aria-selected="true"
|
|
||||||
class="_chat-filter_5qdp0_8"
|
|
||||||
role="option"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
Low priority
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
aria-hidden="false"
|
|
||||||
aria-selected="false"
|
|
||||||
class="_chat-filter_5qdp0_8"
|
|
||||||
role="option"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
People
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="Flex-module_flex RoomListView-module_list"
|
|
||||||
style="--mx-flex-display: flex; --mx-flex-direction: column; --mx-flex-align: start; --mx-flex-justify: start; --mx-flex-gap: 0; --mx-flex-wrap: nowrap;"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="AutoHideScrollbar-module_scrollbar RoomListView-module_scrollbar"
|
|
||||||
tabindex="-1"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="Flex-module_flex RoomListEmptyStateView-module_genericPlaceholder"
|
|
||||||
data-testid="empty-room-list"
|
|
||||||
style="--mx-flex-display: flex; --mx-flex-direction: column; --mx-flex-align: stretch; --mx-flex-justify: center; --mx-flex-gap: var(--cpd-space-2x); --mx-flex-wrap: nowrap;"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="RoomListEmptyStateView-module_title"
|
|
||||||
>
|
|
||||||
You don't have any low priority rooms
|
|
||||||
</span>
|
|
||||||
<button
|
|
||||||
class="_button_1nw83_8"
|
|
||||||
data-kind="tertiary"
|
|
||||||
data-size="lg"
|
|
||||||
role="button"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
See all activity
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`<RoomListView /> > renders EmptyMentionsFilter story 1`] = `
|
exports[`<RoomListView /> > renders EmptyMentionsFilter story 1`] = `
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
@@ -3359,15 +3199,6 @@ exports[`<RoomListView /> > renders EmptyWithoutCreatePermission story 1`] = `
|
|||||||
>
|
>
|
||||||
Rooms
|
Rooms
|
||||||
</button>
|
</button>
|
||||||
<button
|
|
||||||
aria-hidden="false"
|
|
||||||
aria-selected="false"
|
|
||||||
class="_chat-filter_5qdp0_8"
|
|
||||||
role="option"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
Favourites
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -3472,15 +3303,6 @@ exports[`<RoomListView /> > renders LargeFlatList story 1`] = `
|
|||||||
>
|
>
|
||||||
Rooms
|
Rooms
|
||||||
</button>
|
</button>
|
||||||
<button
|
|
||||||
aria-hidden="false"
|
|
||||||
aria-selected="false"
|
|
||||||
class="_chat-filter_5qdp0_8"
|
|
||||||
role="option"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
Favourites
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -8373,15 +8195,6 @@ exports[`<RoomListView /> > renders LargeSectionList story 1`] = `
|
|||||||
>
|
>
|
||||||
Rooms
|
Rooms
|
||||||
</button>
|
</button>
|
||||||
<button
|
|
||||||
aria-hidden="false"
|
|
||||||
aria-selected="false"
|
|
||||||
class="_chat-filter_5qdp0_8"
|
|
||||||
role="option"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
Favourites
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -13434,15 +13247,6 @@ exports[`<RoomListView /> > renders Loading story 1`] = `
|
|||||||
>
|
>
|
||||||
Rooms
|
Rooms
|
||||||
</button>
|
</button>
|
||||||
<button
|
|
||||||
aria-hidden="false"
|
|
||||||
aria-selected="false"
|
|
||||||
class="_chat-filter_5qdp0_8"
|
|
||||||
role="option"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
Favourites
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -13508,15 +13312,6 @@ exports[`<RoomListView /> > renders SmallFlatList story 1`] = `
|
|||||||
>
|
>
|
||||||
Rooms
|
Rooms
|
||||||
</button>
|
</button>
|
||||||
<button
|
|
||||||
aria-hidden="false"
|
|
||||||
aria-selected="false"
|
|
||||||
class="_chat-filter_5qdp0_8"
|
|
||||||
role="option"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
Favourites
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -13870,15 +13665,6 @@ exports[`<RoomListView /> > renders SmallSectionList story 1`] = `
|
|||||||
>
|
>
|
||||||
Rooms
|
Rooms
|
||||||
</button>
|
</button>
|
||||||
<button
|
|
||||||
aria-hidden="false"
|
|
||||||
aria-selected="false"
|
|
||||||
class="_chat-filter_5qdp0_8"
|
|
||||||
role="option"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
Favourites
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -14368,15 +14154,6 @@ exports[`<RoomListView /> > renders Toast story 1`] = `
|
|||||||
>
|
>
|
||||||
Rooms
|
Rooms
|
||||||
</button>
|
</button>
|
||||||
<button
|
|
||||||
aria-hidden="false"
|
|
||||||
aria-selected="false"
|
|
||||||
class="_chat-filter_5qdp0_8"
|
|
||||||
role="option"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
Favourites
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -17067,7 +16844,7 @@ exports[`<RoomListView /> > renders WithActiveFilter story 1`] = `
|
|||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
aria-hidden="false"
|
aria-hidden="false"
|
||||||
aria-selected="false"
|
aria-selected="true"
|
||||||
class="_chat-filter_5qdp0_8"
|
class="_chat-filter_5qdp0_8"
|
||||||
role="option"
|
role="option"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
@@ -17083,15 +16860,6 @@ exports[`<RoomListView /> > renders WithActiveFilter story 1`] = `
|
|||||||
>
|
>
|
||||||
Rooms
|
Rooms
|
||||||
</button>
|
</button>
|
||||||
<button
|
|
||||||
aria-hidden="false"
|
|
||||||
aria-selected="true"
|
|
||||||
class="_chat-filter_5qdp0_8"
|
|
||||||
role="option"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
Favourites
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -131,35 +131,33 @@ export function MoreOptionContent({ vm }: MoreOptionContentProps): JSX.Element {
|
|||||||
hideChevron={true}
|
hideChevron={true}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{snapshot.canMoveToSection && (
|
<SubMenu
|
||||||
<SubMenu
|
trigger={
|
||||||
trigger={
|
<MenuItem
|
||||||
<MenuItem
|
Icon={ArrowRightIcon}
|
||||||
Icon={ArrowRightIcon}
|
label={_t("room_list|more_options|move_to_section")}
|
||||||
label={_t("room_list|more_options|move_to_section")}
|
onSelect={null}
|
||||||
onSelect={null}
|
/>
|
||||||
/>
|
}
|
||||||
}
|
>
|
||||||
>
|
{snapshot.sections.map((section) => (
|
||||||
{snapshot.sections.map((section) => (
|
<MenuItem
|
||||||
<MenuItem
|
key={section.tag}
|
||||||
key={section.tag}
|
label={section.name}
|
||||||
label={section.name}
|
labelProps={{ className: styles.sectionLabel }}
|
||||||
labelProps={{ className: styles.sectionLabel }}
|
onSelect={() => vm.onToggleSection(section.tag)}
|
||||||
onSelect={() => vm.onToggleSection(section.tag)}
|
onClick={(evt) => evt.stopPropagation()}
|
||||||
onClick={(evt) => evt.stopPropagation()}
|
hideChevron={true}
|
||||||
hideChevron={true}
|
aria-checked={section.isSelected}
|
||||||
aria-checked={section.isSelected}
|
>
|
||||||
>
|
{section.isSelected && (
|
||||||
{section.isSelected && (
|
<CheckIcon color="var(--cpd-color-icon-tertiary)" width="24px" height="24px" />
|
||||||
<CheckIcon color="var(--cpd-color-icon-tertiary)" width="24px" height="24px" />
|
)}
|
||||||
)}
|
</MenuItem>
|
||||||
</MenuItem>
|
))}
|
||||||
))}
|
{hasSections && <Separator />}
|
||||||
{hasSections && <Separator />}
|
<MenuItem label={_t("action|new_section")} onSelect={vm.onCreateSection} hideChevron={true} />
|
||||||
<MenuItem label={_t("action|new_section")} onSelect={vm.onCreateSection} hideChevron={true} />
|
</SubMenu>
|
||||||
</SubMenu>
|
|
||||||
)}
|
|
||||||
{isInSection && (
|
{isInSection && (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
Icon={MinusIcon}
|
Icon={MinusIcon}
|
||||||
|
|||||||
@@ -92,8 +92,6 @@ export interface RoomListItemViewSnapshot {
|
|||||||
canMarkAsUnread: boolean;
|
canMarkAsUnread: boolean;
|
||||||
/** The room's notification state */
|
/** The room's notification state */
|
||||||
roomNotifState: RoomNotifState;
|
roomNotifState: RoomNotifState;
|
||||||
/** Whether the room can be moved to a section */
|
|
||||||
canMoveToSection: boolean;
|
|
||||||
/** Available sections the room can be assigned to */
|
/** Available sections the room can be assigned to */
|
||||||
sections: Section[];
|
sections: Section[];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ export const defaultSnapshot: RoomListItemViewSnapshot = {
|
|||||||
canMarkAsRead: false,
|
canMarkAsRead: false,
|
||||||
canMarkAsUnread: true,
|
canMarkAsUnread: true,
|
||||||
roomNotifState: RoomNotifState.AllMessages,
|
roomNotifState: RoomNotifState.AllMessages,
|
||||||
canMoveToSection: true,
|
|
||||||
sections: [
|
sections: [
|
||||||
{
|
{
|
||||||
tag: "m.favourite",
|
tag: "m.favourite",
|
||||||
|
|||||||
@@ -105,7 +105,6 @@ export const createMockRoomSnapshot = (id: string, name: string, index: number):
|
|||||||
canMarkAsRead: false,
|
canMarkAsRead: false,
|
||||||
canMarkAsUnread: true,
|
canMarkAsUnread: true,
|
||||||
roomNotifState: RoomNotifState.AllMessages,
|
roomNotifState: RoomNotifState.AllMessages,
|
||||||
canMoveToSection: true,
|
|
||||||
sections: [],
|
sections: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||