New Room List: Create new labs flag (#29239)
* Create new labs flag * Render empty room list view * Reload on flag change * Rename RoomList.tsx to LegacyRoomList.tsx and rename NewRoomListView.tsx to RoomListView.tsx * Update labs.md
This commit is contained in:
@@ -112,3 +112,7 @@ Unreliable in encrypted rooms.
|
|||||||
## Knock rooms (`feature_ask_to_join`) [In Development]
|
## Knock rooms (`feature_ask_to_join`) [In Development]
|
||||||
|
|
||||||
Enables knock feature for rooms. This allows users to ask to join a room.
|
Enables knock feature for rooms. This allows users to ask to join a room.
|
||||||
|
|
||||||
|
## New room list (`feature_new_room_list`) [In Development]
|
||||||
|
|
||||||
|
Enable the new room list that is currently in development.
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import classNames from "classnames";
|
|||||||
|
|
||||||
import dis from "../../dispatcher/dispatcher";
|
import dis from "../../dispatcher/dispatcher";
|
||||||
import { _t } from "../../languageHandler";
|
import { _t } from "../../languageHandler";
|
||||||
import RoomList from "../views/rooms/RoomList";
|
import LegacyRoomList from "../views/rooms/LegacyRoomList";
|
||||||
import LegacyCallHandler, { LegacyCallHandlerEvent } from "../../LegacyCallHandler";
|
import LegacyCallHandler, { LegacyCallHandlerEvent } from "../../LegacyCallHandler";
|
||||||
import { HEADER_HEIGHT } from "../views/rooms/RoomSublist";
|
import { HEADER_HEIGHT } from "../views/rooms/RoomSublist";
|
||||||
import { Action } from "../../dispatcher/actions";
|
import { Action } from "../../dispatcher/actions";
|
||||||
@@ -36,6 +36,8 @@ import AccessibleButton, { type ButtonEvent } from "../views/elements/Accessible
|
|||||||
import PosthogTrackers from "../../PosthogTrackers";
|
import PosthogTrackers from "../../PosthogTrackers";
|
||||||
import type PageType from "../../PageTypes";
|
import type PageType from "../../PageTypes";
|
||||||
import { Landmark, LandmarkNavigation } from "../../accessibility/LandmarkNavigation";
|
import { Landmark, LandmarkNavigation } from "../../accessibility/LandmarkNavigation";
|
||||||
|
import SettingsStore from "../../settings/SettingsStore";
|
||||||
|
import { RoomListView } from "../views/rooms/RoomListView";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
isMinimized: boolean;
|
isMinimized: boolean;
|
||||||
@@ -56,7 +58,7 @@ interface IState {
|
|||||||
|
|
||||||
export default class LeftPanel extends React.Component<IProps, IState> {
|
export default class LeftPanel extends React.Component<IProps, IState> {
|
||||||
private listContainerRef = createRef<HTMLDivElement>();
|
private listContainerRef = createRef<HTMLDivElement>();
|
||||||
private roomListRef = createRef<RoomList>();
|
private roomListRef = createRef<LegacyRoomList>();
|
||||||
private focusedElement: Element | null = null;
|
private focusedElement: Element | null = null;
|
||||||
private isDoingStickyHeaders = false;
|
private isDoingStickyHeaders = false;
|
||||||
|
|
||||||
@@ -377,8 +379,25 @@ export default class LeftPanel extends React.Component<IProps, IState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public render(): React.ReactNode {
|
public render(): React.ReactNode {
|
||||||
|
const containerClasses = classNames({
|
||||||
|
mx_LeftPanel: true,
|
||||||
|
mx_LeftPanel_minimized: this.props.isMinimized,
|
||||||
|
});
|
||||||
|
|
||||||
|
const roomListClasses = classNames("mx_LeftPanel_actualRoomListContainer", "mx_AutoHideScrollbar");
|
||||||
|
const useNewRoomList = SettingsStore.getValue("feature_new_room_list");
|
||||||
|
if (useNewRoomList) {
|
||||||
|
return (
|
||||||
|
<div className={containerClasses}>
|
||||||
|
<div className="mx_LeftPanel_roomListContainer">
|
||||||
|
<RoomListView />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const roomList = (
|
const roomList = (
|
||||||
<RoomList
|
<LegacyRoomList
|
||||||
onKeyDown={this.onKeyDown}
|
onKeyDown={this.onKeyDown}
|
||||||
resizeNotifier={this.props.resizeNotifier}
|
resizeNotifier={this.props.resizeNotifier}
|
||||||
onFocus={this.onFocus}
|
onFocus={this.onFocus}
|
||||||
@@ -391,13 +410,6 @@ export default class LeftPanel extends React.Component<IProps, IState> {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
const containerClasses = classNames({
|
|
||||||
mx_LeftPanel: true,
|
|
||||||
mx_LeftPanel_minimized: this.props.isMinimized,
|
|
||||||
});
|
|
||||||
|
|
||||||
const roomListClasses = classNames("mx_LeftPanel_actualRoomListContainer", "mx_AutoHideScrollbar");
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={containerClasses}>
|
<div className={containerClasses}>
|
||||||
<div className="mx_LeftPanel_roomListContainer">
|
<div className="mx_LeftPanel_roomListContainer">
|
||||||
|
|||||||
@@ -9,26 +9,26 @@ Please see LICENSE files in the repository root for full details.
|
|||||||
import { EventType, type Room, RoomType } from "matrix-js-sdk/src/matrix";
|
import { EventType, type Room, RoomType } from "matrix-js-sdk/src/matrix";
|
||||||
import React, { type ComponentType, createRef, type ReactComponentElement, type SyntheticEvent } from "react";
|
import React, { type ComponentType, createRef, type ReactComponentElement, type SyntheticEvent } from "react";
|
||||||
|
|
||||||
import { type IState as IRovingTabIndexState, RovingTabIndexProvider } from "../../../accessibility/RovingTabIndex";
|
import { type IState as IRovingTabIndexState, RovingTabIndexProvider } from "../../../accessibility/RovingTabIndex.tsx";
|
||||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
import MatrixClientContext from "../../../contexts/MatrixClientContext.tsx";
|
||||||
import { shouldShowComponent } from "../../../customisations/helpers/UIComponents";
|
import { shouldShowComponent } from "../../../customisations/helpers/UIComponents.ts";
|
||||||
import { Action } from "../../../dispatcher/actions";
|
import { Action } from "../../../dispatcher/actions.ts";
|
||||||
import defaultDispatcher from "../../../dispatcher/dispatcher";
|
import defaultDispatcher from "../../../dispatcher/dispatcher.ts";
|
||||||
import { type ActionPayload } from "../../../dispatcher/payloads";
|
import { type ActionPayload } from "../../../dispatcher/payloads.ts";
|
||||||
import { type ViewRoomDeltaPayload } from "../../../dispatcher/payloads/ViewRoomDeltaPayload";
|
import { type ViewRoomDeltaPayload } from "../../../dispatcher/payloads/ViewRoomDeltaPayload.ts";
|
||||||
import { type ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
|
import { type ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload.ts";
|
||||||
import { useEventEmitterState } from "../../../hooks/useEventEmitter";
|
import { useEventEmitterState } from "../../../hooks/useEventEmitter.ts";
|
||||||
import { _t, _td, type TranslationKey } from "../../../languageHandler";
|
import { _t, _td, type TranslationKey } from "../../../languageHandler.tsx";
|
||||||
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
import { MatrixClientPeg } from "../../../MatrixClientPeg.ts";
|
||||||
import PosthogTrackers from "../../../PosthogTrackers";
|
import PosthogTrackers from "../../../PosthogTrackers.ts";
|
||||||
import SettingsStore from "../../../settings/SettingsStore";
|
import SettingsStore from "../../../settings/SettingsStore.ts";
|
||||||
import { useFeatureEnabled } from "../../../hooks/useSettings";
|
import { useFeatureEnabled } from "../../../hooks/useSettings.ts";
|
||||||
import { UIComponent } from "../../../settings/UIFeature";
|
import { UIComponent } from "../../../settings/UIFeature.ts";
|
||||||
import { RoomNotificationStateStore } from "../../../stores/notifications/RoomNotificationStateStore";
|
import { RoomNotificationStateStore } from "../../../stores/notifications/RoomNotificationStateStore.ts";
|
||||||
import { type ITagMap } from "../../../stores/room-list/algorithms/models";
|
import { type ITagMap } from "../../../stores/room-list/algorithms/models.ts";
|
||||||
import { DefaultTagID, type TagID } from "../../../stores/room-list/models";
|
import { DefaultTagID, type TagID } from "../../../stores/room-list/models.ts";
|
||||||
import { UPDATE_EVENT } from "../../../stores/AsyncStore";
|
import { UPDATE_EVENT } from "../../../stores/AsyncStore.ts";
|
||||||
import RoomListStore, { LISTS_UPDATE_EVENT } from "../../../stores/room-list/RoomListStore";
|
import RoomListStore, { LISTS_UPDATE_EVENT } from "../../../stores/room-list/RoomListStore.ts";
|
||||||
import {
|
import {
|
||||||
isMetaSpace,
|
isMetaSpace,
|
||||||
type ISuggestedRoom,
|
type ISuggestedRoom,
|
||||||
@@ -36,26 +36,36 @@ import {
|
|||||||
type SpaceKey,
|
type SpaceKey,
|
||||||
UPDATE_SELECTED_SPACE,
|
UPDATE_SELECTED_SPACE,
|
||||||
UPDATE_SUGGESTED_ROOMS,
|
UPDATE_SUGGESTED_ROOMS,
|
||||||
} from "../../../stores/spaces";
|
} from "../../../stores/spaces/index.ts";
|
||||||
import SpaceStore from "../../../stores/spaces/SpaceStore";
|
import SpaceStore from "../../../stores/spaces/SpaceStore.ts";
|
||||||
import { arrayFastClone, arrayHasDiff } from "../../../utils/arrays";
|
import { arrayFastClone, arrayHasDiff } from "../../../utils/arrays.ts";
|
||||||
import { objectShallowClone, objectWithOnly } from "../../../utils/objects";
|
import { objectShallowClone, objectWithOnly } from "../../../utils/objects.ts";
|
||||||
import type ResizeNotifier from "../../../utils/ResizeNotifier";
|
import type ResizeNotifier from "../../../utils/ResizeNotifier.ts";
|
||||||
import { shouldShowSpaceInvite, showAddExistingRooms, showCreateNewRoom, showSpaceInvite } from "../../../utils/space";
|
import {
|
||||||
import { ChevronFace, ContextMenuTooltipButton, type MenuProps, useContextMenu } from "../../structures/ContextMenu";
|
shouldShowSpaceInvite,
|
||||||
import RoomAvatar from "../avatars/RoomAvatar";
|
showAddExistingRooms,
|
||||||
import { BetaPill } from "../beta/BetaCard";
|
showCreateNewRoom,
|
||||||
|
showSpaceInvite,
|
||||||
|
} from "../../../utils/space.tsx";
|
||||||
|
import {
|
||||||
|
ChevronFace,
|
||||||
|
ContextMenuTooltipButton,
|
||||||
|
type MenuProps,
|
||||||
|
useContextMenu,
|
||||||
|
} from "../../structures/ContextMenu.tsx";
|
||||||
|
import RoomAvatar from "../avatars/RoomAvatar.tsx";
|
||||||
|
import { BetaPill } from "../beta/BetaCard.tsx";
|
||||||
import IconizedContextMenu, {
|
import IconizedContextMenu, {
|
||||||
IconizedContextMenuOption,
|
IconizedContextMenuOption,
|
||||||
IconizedContextMenuOptionList,
|
IconizedContextMenuOptionList,
|
||||||
} from "../context_menus/IconizedContextMenu";
|
} from "../context_menus/IconizedContextMenu.tsx";
|
||||||
import ExtraTile from "./ExtraTile";
|
import ExtraTile from "./ExtraTile.tsx";
|
||||||
import RoomSublist, { type IAuxButtonProps } from "./RoomSublist";
|
import RoomSublist, { type IAuxButtonProps } from "./RoomSublist.tsx";
|
||||||
import { SdkContextClass } from "../../../contexts/SDKContext";
|
import { SdkContextClass } from "../../../contexts/SDKContext.ts";
|
||||||
import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts";
|
import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts.ts";
|
||||||
import { getKeyBindingsManager } from "../../../KeyBindingsManager";
|
import { getKeyBindingsManager } from "../../../KeyBindingsManager.ts";
|
||||||
import AccessibleButton from "../elements/AccessibleButton";
|
import AccessibleButton from "../elements/AccessibleButton.tsx";
|
||||||
import { Landmark, LandmarkNavigation } from "../../../accessibility/LandmarkNavigation";
|
import { Landmark, LandmarkNavigation } from "../../../accessibility/LandmarkNavigation.ts";
|
||||||
import LegacyCallHandler, { LegacyCallHandlerEvent } from "../../../LegacyCallHandler.tsx";
|
import LegacyCallHandler, { LegacyCallHandlerEvent } from "../../../LegacyCallHandler.tsx";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
@@ -420,7 +430,7 @@ const TAG_AESTHETICS: TagAestheticsMap = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class RoomList extends React.PureComponent<IProps, IState> {
|
export default class LegacyRoomList extends React.PureComponent<IProps, IState> {
|
||||||
private dispatcherRef?: string;
|
private dispatcherRef?: string;
|
||||||
private treeRef = createRef<HTMLDivElement>();
|
private treeRef = createRef<HTMLDivElement>();
|
||||||
|
|
||||||
14
src/components/views/rooms/RoomListView.tsx
Normal file
14
src/components/views/rooms/RoomListView.tsx
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2025 New Vector Ltd.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
||||||
|
Please see LICENSE files in the repository root for full details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
type IProps = unknown;
|
||||||
|
|
||||||
|
export const RoomListView: React.FC<IProps> = (props: IProps) => {
|
||||||
|
return <div>New Room List</div>;
|
||||||
|
};
|
||||||
@@ -1496,6 +1496,7 @@
|
|||||||
"location_share_live_description": "Temporary implementation. Locations persist in room history.",
|
"location_share_live_description": "Temporary implementation. Locations persist in room history.",
|
||||||
"mjolnir": "New ways to ignore people",
|
"mjolnir": "New ways to ignore people",
|
||||||
"msc3531_hide_messages_pending_moderation": "Let moderators hide messages pending moderation.",
|
"msc3531_hide_messages_pending_moderation": "Let moderators hide messages pending moderation.",
|
||||||
|
"new_room_list": "Enable new room list",
|
||||||
"notification_settings": "New Notification Settings",
|
"notification_settings": "New Notification Settings",
|
||||||
"notification_settings_beta_caption": "Introducing a simpler way to change your notification settings. Customize your %(brand)s, just the way you like.",
|
"notification_settings_beta_caption": "Introducing a simpler way to change your notification settings. Customize your %(brand)s, just the way you like.",
|
||||||
"notification_settings_beta_title": "Notification Settings",
|
"notification_settings_beta_title": "Notification Settings",
|
||||||
|
|||||||
@@ -205,6 +205,7 @@ export interface Settings {
|
|||||||
"feature_location_share_live": IFeature;
|
"feature_location_share_live": IFeature;
|
||||||
"feature_dynamic_room_predecessors": IFeature;
|
"feature_dynamic_room_predecessors": IFeature;
|
||||||
"feature_render_reaction_images": IFeature;
|
"feature_render_reaction_images": IFeature;
|
||||||
|
"feature_new_room_list": IFeature;
|
||||||
"feature_ask_to_join": IFeature;
|
"feature_ask_to_join": IFeature;
|
||||||
"feature_notifications": IFeature;
|
"feature_notifications": IFeature;
|
||||||
// These are in the feature namespace but aren't actually features
|
// These are in the feature namespace but aren't actually features
|
||||||
@@ -623,6 +624,15 @@ export const SETTINGS: Settings = {
|
|||||||
supportedLevelsAreOrdered: true,
|
supportedLevelsAreOrdered: true,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
"feature_new_room_list": {
|
||||||
|
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG_PRIORITISED,
|
||||||
|
labsGroup: LabGroup.Ui,
|
||||||
|
displayName: _td("labs|new_room_list"),
|
||||||
|
description: _td("labs|under_active_development"),
|
||||||
|
isFeature: true,
|
||||||
|
default: false,
|
||||||
|
controller: new ReloadOnChangeController(),
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* With the transition to Compound we are moving to a base font size
|
* With the transition to Compound we are moving to a base font size
|
||||||
* of 16px. We're taking the opportunity to move away from the `baseFontSize`
|
* of 16px. We're taking the opportunity to move away from the `baseFontSize`
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ import { setDiff, setHasDiff } from "../../utils/sets";
|
|||||||
import { Action } from "../../dispatcher/actions";
|
import { Action } from "../../dispatcher/actions";
|
||||||
import { arrayHasDiff, arrayHasOrderChange, filterBoolean } from "../../utils/arrays";
|
import { arrayHasDiff, arrayHasOrderChange, filterBoolean } from "../../utils/arrays";
|
||||||
import { reorderLexicographically } from "../../utils/stringOrderField";
|
import { reorderLexicographically } from "../../utils/stringOrderField";
|
||||||
import { TAG_ORDER } from "../../components/views/rooms/RoomList";
|
import { TAG_ORDER } from "../../components/views/rooms/LegacyRoomList";
|
||||||
import { type SettingUpdatedPayload } from "../../dispatcher/payloads/SettingUpdatedPayload";
|
import { type SettingUpdatedPayload } from "../../dispatcher/payloads/SettingUpdatedPayload";
|
||||||
import {
|
import {
|
||||||
isMetaSpace,
|
isMetaSpace,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import userEvent from "@testing-library/user-event";
|
|||||||
import { mocked } from "jest-mock";
|
import { mocked } from "jest-mock";
|
||||||
import { type Room } from "matrix-js-sdk/src/matrix";
|
import { type Room } from "matrix-js-sdk/src/matrix";
|
||||||
|
|
||||||
import RoomList from "../../../../../src/components/views/rooms/RoomList";
|
import LegacyRoomList from "../../../../../src/components/views/rooms/LegacyRoomList";
|
||||||
import ResizeNotifier from "../../../../../src/utils/ResizeNotifier";
|
import ResizeNotifier from "../../../../../src/utils/ResizeNotifier";
|
||||||
import { MetaSpace } from "../../../../../src/stores/spaces";
|
import { MetaSpace } from "../../../../../src/stores/spaces";
|
||||||
import { shouldShowComponent } from "../../../../../src/customisations/helpers/UIComponents";
|
import { shouldShowComponent } from "../../../../../src/customisations/helpers/UIComponents";
|
||||||
@@ -40,14 +40,14 @@ const getDMRoomsForUserId = jest.fn();
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
DMRoomMap.sharedInstance = { getUserIdForRoomId, getDMRoomsForUserId };
|
DMRoomMap.sharedInstance = { getUserIdForRoomId, getDMRoomsForUserId };
|
||||||
|
|
||||||
describe("RoomList", () => {
|
describe("LegacyRoomList", () => {
|
||||||
stubClient();
|
stubClient();
|
||||||
const client = MatrixClientPeg.safeGet();
|
const client = MatrixClientPeg.safeGet();
|
||||||
const store = SpaceStore.instance;
|
const store = SpaceStore.instance;
|
||||||
|
|
||||||
function getComponent(props: Partial<RoomList["props"]> = {}): JSX.Element {
|
function getComponent(props: Partial<LegacyRoomList["props"]> = {}): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<RoomList
|
<LegacyRoomList
|
||||||
onKeyDown={jest.fn()}
|
onKeyDown={jest.fn()}
|
||||||
onFocus={jest.fn()}
|
onFocus={jest.fn()}
|
||||||
onBlur={jest.fn()}
|
onBlur={jest.fn()}
|
||||||
Reference in New Issue
Block a user