Remove unused code left over from the old search (#8947)
This commit is contained in:
parent
424d33d4b0
commit
328d7ea5eb
11 changed files with 102 additions and 466 deletions
|
@ -217,14 +217,6 @@ $roomListCollapsedWidth: 68px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_LeftPanel_roomListFilterCount {
|
|
||||||
font-size: $font-13px;
|
|
||||||
font-weight: $font-semi-bold;
|
|
||||||
margin-left: 12px;
|
|
||||||
margin-top: 14px;
|
|
||||||
margin-bottom: -4px; // to counteract the normal roomListWrapper margin-top
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_LeftPanel_roomListWrapper {
|
.mx_LeftPanel_roomListWrapper {
|
||||||
// Make the y-scrollbar more responsive
|
// Make the y-scrollbar more responsive
|
||||||
padding-right: 2px;
|
padding-right: 2px;
|
||||||
|
|
|
@ -14,35 +14,30 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { ComponentType, createRef, ReactComponentElement, RefObject } from "react";
|
|
||||||
import { Room } from "matrix-js-sdk/src/models/room";
|
|
||||||
import { RoomType, EventType } from "matrix-js-sdk/src/@types/event";
|
|
||||||
import * as fbEmitter from "fbemitter";
|
import * as fbEmitter from "fbemitter";
|
||||||
|
import { EventType, RoomType } from "matrix-js-sdk/src/@types/event";
|
||||||
|
import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
|
import React, { ComponentType, createRef, ReactComponentElement, RefObject } from "react";
|
||||||
|
|
||||||
import { _t, _td } from "../../../languageHandler";
|
|
||||||
import { IState as IRovingTabIndexState, RovingTabIndexProvider } from "../../../accessibility/RovingTabIndex";
|
import { IState as IRovingTabIndexState, RovingTabIndexProvider } from "../../../accessibility/RovingTabIndex";
|
||||||
import ResizeNotifier from "../../../utils/ResizeNotifier";
|
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||||
import RoomListStore, { LISTS_UPDATE_EVENT } from "../../../stores/room-list/RoomListStore";
|
import { shouldShowComponent } from "../../../customisations/helpers/UIComponents";
|
||||||
import { RoomViewStore } from "../../../stores/RoomViewStore";
|
import { Action } from "../../../dispatcher/actions";
|
||||||
|
import defaultDispatcher from "../../../dispatcher/dispatcher";
|
||||||
|
import { ActionPayload } from "../../../dispatcher/payloads";
|
||||||
|
import { ViewRoomDeltaPayload } from "../../../dispatcher/payloads/ViewRoomDeltaPayload";
|
||||||
|
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
|
||||||
|
import { useEventEmitterState } from "../../../hooks/useEventEmitter";
|
||||||
|
import { _t, _td } from "../../../languageHandler";
|
||||||
|
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||||
|
import PosthogTrackers from "../../../PosthogTrackers";
|
||||||
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
|
import { UIComponent } from "../../../settings/UIFeature";
|
||||||
|
import { RoomNotificationStateStore } from "../../../stores/notifications/RoomNotificationStateStore";
|
||||||
import { ITagMap } from "../../../stores/room-list/algorithms/models";
|
import { ITagMap } from "../../../stores/room-list/algorithms/models";
|
||||||
import { DefaultTagID, TagID } from "../../../stores/room-list/models";
|
import { DefaultTagID, TagID } from "../../../stores/room-list/models";
|
||||||
import defaultDispatcher from "../../../dispatcher/dispatcher";
|
import RoomListStore, { LISTS_UPDATE_EVENT } from "../../../stores/room-list/RoomListStore";
|
||||||
import RoomSublist, { IAuxButtonProps } from "./RoomSublist";
|
import { RoomViewStore } from "../../../stores/RoomViewStore";
|
||||||
import { ActionPayload } from "../../../dispatcher/payloads";
|
|
||||||
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
|
||||||
import ExtraTile from "./ExtraTile";
|
|
||||||
import { Action } from "../../../dispatcher/actions";
|
|
||||||
import { ViewRoomDeltaPayload } from "../../../dispatcher/payloads/ViewRoomDeltaPayload";
|
|
||||||
import { RoomNotificationStateStore } from "../../../stores/notifications/RoomNotificationStateStore";
|
|
||||||
import { arrayFastClone, arrayHasDiff } from "../../../utils/arrays";
|
|
||||||
import { objectShallowClone, objectWithOnly } from "../../../utils/objects";
|
|
||||||
import IconizedContextMenu, {
|
|
||||||
IconizedContextMenuOption,
|
|
||||||
IconizedContextMenuOptionList,
|
|
||||||
} from "../context_menus/IconizedContextMenu";
|
|
||||||
import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton";
|
|
||||||
import { BetaPill } from "../beta/BetaCard";
|
|
||||||
import SpaceStore from "../../../stores/spaces/SpaceStore";
|
|
||||||
import {
|
import {
|
||||||
isMetaSpace,
|
isMetaSpace,
|
||||||
ISuggestedRoom,
|
ISuggestedRoom,
|
||||||
|
@ -51,17 +46,21 @@ import {
|
||||||
UPDATE_SELECTED_SPACE,
|
UPDATE_SELECTED_SPACE,
|
||||||
UPDATE_SUGGESTED_ROOMS,
|
UPDATE_SUGGESTED_ROOMS,
|
||||||
} from "../../../stores/spaces";
|
} from "../../../stores/spaces";
|
||||||
|
import SpaceStore from "../../../stores/spaces/SpaceStore";
|
||||||
|
import { arrayFastClone, arrayHasDiff } from "../../../utils/arrays";
|
||||||
|
import { objectShallowClone, objectWithOnly } from "../../../utils/objects";
|
||||||
|
import ResizeNotifier from "../../../utils/ResizeNotifier";
|
||||||
import { shouldShowSpaceInvite, showAddExistingRooms, showCreateNewRoom, showSpaceInvite } from "../../../utils/space";
|
import { shouldShowSpaceInvite, showAddExistingRooms, showCreateNewRoom, showSpaceInvite } from "../../../utils/space";
|
||||||
import RoomAvatar from "../avatars/RoomAvatar";
|
|
||||||
import { shouldShowComponent } from "../../../customisations/helpers/UIComponents";
|
|
||||||
import { UIComponent } from "../../../settings/UIFeature";
|
|
||||||
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
|
|
||||||
import { useEventEmitterState } from "../../../hooks/useEventEmitter";
|
|
||||||
import { ChevronFace, ContextMenuTooltipButton, useContextMenu } from "../../structures/ContextMenu";
|
import { ChevronFace, ContextMenuTooltipButton, useContextMenu } from "../../structures/ContextMenu";
|
||||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
import RoomAvatar from "../avatars/RoomAvatar";
|
||||||
import SettingsStore from "../../../settings/SettingsStore";
|
import { BetaPill } from "../beta/BetaCard";
|
||||||
import PosthogTrackers from "../../../PosthogTrackers";
|
import IconizedContextMenu, {
|
||||||
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
|
IconizedContextMenuOption,
|
||||||
|
IconizedContextMenuOptionList,
|
||||||
|
} from "../context_menus/IconizedContextMenu";
|
||||||
|
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
|
||||||
|
import ExtraTile from "./ExtraTile";
|
||||||
|
import RoomSublist, { IAuxButtonProps } from "./RoomSublist";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
onKeyDown: (ev: React.KeyboardEvent, state: IRovingTabIndexState) => void;
|
onKeyDown: (ev: React.KeyboardEvent, state: IRovingTabIndexState) => void;
|
||||||
|
@ -76,7 +75,6 @@ interface IProps {
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
sublists: ITagMap;
|
sublists: ITagMap;
|
||||||
isNameFiltering: boolean;
|
|
||||||
currentRoomId?: string;
|
currentRoomId?: string;
|
||||||
suggestedRooms: ISuggestedRoom[];
|
suggestedRooms: ISuggestedRoom[];
|
||||||
}
|
}
|
||||||
|
@ -403,7 +401,6 @@ export default class RoomList extends React.PureComponent<IProps, IState> {
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
sublists: {},
|
sublists: {},
|
||||||
isNameFiltering: !!RoomListStore.instance.getFirstNameFilterCondition(),
|
|
||||||
suggestedRooms: SpaceStore.instance.suggestedRooms,
|
suggestedRooms: SpaceStore.instance.suggestedRooms,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -480,8 +477,7 @@ export default class RoomList extends React.PureComponent<IProps, IState> {
|
||||||
const previousListIds = Object.keys(this.state.sublists);
|
const previousListIds = Object.keys(this.state.sublists);
|
||||||
const newListIds = Object.keys(newLists);
|
const newListIds = Object.keys(newLists);
|
||||||
|
|
||||||
const isNameFiltering = !!RoomListStore.instance.getFirstNameFilterCondition();
|
let doUpdate = arrayHasDiff(previousListIds, newListIds);
|
||||||
let doUpdate = this.state.isNameFiltering !== isNameFiltering || arrayHasDiff(previousListIds, newListIds);
|
|
||||||
if (!doUpdate) {
|
if (!doUpdate) {
|
||||||
// so we didn't have the visible sublists change, but did the contents of those
|
// so we didn't have the visible sublists change, but did the contents of those
|
||||||
// sublists change significantly enough to break the sticky headers? Probably, so
|
// sublists change significantly enough to break the sticky headers? Probably, so
|
||||||
|
@ -503,33 +499,12 @@ export default class RoomList extends React.PureComponent<IProps, IState> {
|
||||||
const newSublists = objectWithOnly(newLists, newListIds);
|
const newSublists = objectWithOnly(newLists, newListIds);
|
||||||
const sublists = objectShallowClone(newSublists, (k, v) => arrayFastClone(v));
|
const sublists = objectShallowClone(newSublists, (k, v) => arrayFastClone(v));
|
||||||
|
|
||||||
this.setState({ sublists, isNameFiltering }, () => {
|
this.setState({ sublists }, () => {
|
||||||
this.props.onResize();
|
this.props.onResize();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private onStartChat = (ev: ButtonEvent) => {
|
|
||||||
const initialText = RoomListStore.instance.getFirstNameFilterCondition()?.search;
|
|
||||||
defaultDispatcher.dispatch({ action: "view_create_chat", initialText });
|
|
||||||
PosthogTrackers.trackInteraction("WebRoomListRoomsSublistPlusMenuCreateChatItem", ev);
|
|
||||||
};
|
|
||||||
|
|
||||||
private onExplore = (ev: ButtonEvent) => {
|
|
||||||
if (!isMetaSpace(this.props.activeSpace)) {
|
|
||||||
defaultDispatcher.dispatch<ViewRoomPayload>({
|
|
||||||
action: Action.ViewRoom,
|
|
||||||
room_id: this.props.activeSpace,
|
|
||||||
metricsTrigger: undefined, // other
|
|
||||||
});
|
|
||||||
PosthogTrackers.trackInteraction("WebRoomListRoomsSublistPlusMenuExploreRoomsItem", ev);
|
|
||||||
} else {
|
|
||||||
const initialText = RoomListStore.instance.getFirstNameFilterCondition()?.search;
|
|
||||||
defaultDispatcher.dispatch({ action: Action.ViewRoomDirectory, initialText });
|
|
||||||
PosthogTrackers.trackInteraction("WebRoomListRoomsSublistPlusMenuExploreRoomsItem", ev);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private renderSuggestedRooms(): ReactComponentElement<typeof ExtraTile>[] {
|
private renderSuggestedRooms(): ReactComponentElement<typeof ExtraTile>[] {
|
||||||
return this.state.suggestedRooms.map(room => {
|
return this.state.suggestedRooms.map(room => {
|
||||||
const name = room.name || room.canonical_alias || room.aliases?.[0] || _t("Empty room");
|
const name = room.name || room.canonical_alias || room.aliases?.[0] || _t("Empty room");
|
||||||
|
@ -573,8 +548,8 @@ export default class RoomList extends React.PureComponent<IProps, IState> {
|
||||||
|
|
||||||
private renderSublists(): React.ReactElement[] {
|
private renderSublists(): React.ReactElement[] {
|
||||||
// show a skeleton UI if the user is in no rooms and they are not filtering and have no suggested rooms
|
// show a skeleton UI if the user is in no rooms and they are not filtering and have no suggested rooms
|
||||||
const showSkeleton = !this.state.isNameFiltering && !this.state.suggestedRooms?.length &&
|
const showSkeleton = !this.state.suggestedRooms?.length &&
|
||||||
Object.values(RoomListStore.instance.unfilteredLists).every(list => !list?.length);
|
Object.values(RoomListStore.instance.orderedLists).every(list => !list?.length);
|
||||||
|
|
||||||
return TAG_ORDER
|
return TAG_ORDER
|
||||||
.map(orderedTagId => {
|
.map(orderedTagId => {
|
||||||
|
@ -636,29 +611,6 @@ export default class RoomList extends React.PureComponent<IProps, IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
let explorePrompt: JSX.Element;
|
|
||||||
if (!this.props.isMinimized) {
|
|
||||||
if (this.state.isNameFiltering) {
|
|
||||||
explorePrompt = <div className="mx_RoomList_explorePrompt">
|
|
||||||
<div>{ _t("Can't see what you're looking for?") }</div>
|
|
||||||
<AccessibleButton
|
|
||||||
className="mx_RoomList_explorePrompt_startChat"
|
|
||||||
kind="link"
|
|
||||||
onClick={this.onStartChat}
|
|
||||||
>
|
|
||||||
{ _t("Start a new chat") }
|
|
||||||
</AccessibleButton>
|
|
||||||
<AccessibleButton
|
|
||||||
className="mx_RoomList_explorePrompt_explore"
|
|
||||||
kind="link"
|
|
||||||
onClick={this.onExplore}
|
|
||||||
>
|
|
||||||
{ !isMetaSpace(this.props.activeSpace) ? _t("Explore rooms") : _t("Explore all public rooms") }
|
|
||||||
</AccessibleButton>
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const sublists = this.renderSublists();
|
const sublists = this.renderSublists();
|
||||||
return (
|
return (
|
||||||
<RovingTabIndexProvider handleHomeEnd handleUpDown onKeyDown={this.props.onKeyDown}>
|
<RovingTabIndexProvider handleHomeEnd handleUpDown onKeyDown={this.props.onKeyDown}>
|
||||||
|
@ -673,7 +625,6 @@ export default class RoomList extends React.PureComponent<IProps, IState> {
|
||||||
ref={this.treeRef}
|
ref={this.treeRef}
|
||||||
>
|
>
|
||||||
{ sublists }
|
{ sublists }
|
||||||
{ explorePrompt }
|
|
||||||
</div>
|
</div>
|
||||||
) }
|
) }
|
||||||
</RovingTabIndexProvider>
|
</RovingTabIndexProvider>
|
||||||
|
|
|
@ -14,35 +14,22 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useContext, useEffect, useState } from "react";
|
|
||||||
import { Room, RoomEvent } from "matrix-js-sdk/src/models/room";
|
|
||||||
import { EventType, RoomType } from "matrix-js-sdk/src/@types/event";
|
import { EventType, RoomType } from "matrix-js-sdk/src/@types/event";
|
||||||
import { ClientEvent } from "matrix-js-sdk/src/client";
|
import { ClientEvent } from "matrix-js-sdk/src/client";
|
||||||
|
import { Room, RoomEvent } from "matrix-js-sdk/src/models/room";
|
||||||
|
import React, { useContext, useEffect, useState } from "react";
|
||||||
|
|
||||||
import { _t } from "../../../languageHandler";
|
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||||
|
import { shouldShowComponent } from "../../../customisations/helpers/UIComponents";
|
||||||
|
import { Action } from "../../../dispatcher/actions";
|
||||||
|
import defaultDispatcher from "../../../dispatcher/dispatcher";
|
||||||
|
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
|
||||||
|
import { useDispatcher } from "../../../hooks/useDispatcher";
|
||||||
import { useEventEmitterState, useTypedEventEmitter, useTypedEventEmitterState } from "../../../hooks/useEventEmitter";
|
import { useEventEmitterState, useTypedEventEmitter, useTypedEventEmitterState } from "../../../hooks/useEventEmitter";
|
||||||
import { useFeatureEnabled } from "../../../hooks/useSettings";
|
import { useFeatureEnabled } from "../../../hooks/useSettings";
|
||||||
import SpaceStore from "../../../stores/spaces/SpaceStore";
|
import { _t } from "../../../languageHandler";
|
||||||
import { ChevronFace, ContextMenuTooltipButton, useContextMenu } from "../../structures/ContextMenu";
|
import PosthogTrackers from "../../../PosthogTrackers";
|
||||||
import SpaceContextMenu from "../context_menus/SpaceContextMenu";
|
import { UIComponent } from "../../../settings/UIFeature";
|
||||||
import { HomeButtonContextMenu } from "../spaces/SpacePanel";
|
|
||||||
import IconizedContextMenu, {
|
|
||||||
IconizedContextMenuOption,
|
|
||||||
IconizedContextMenuOptionList,
|
|
||||||
} from "../context_menus/IconizedContextMenu";
|
|
||||||
import defaultDispatcher from "../../../dispatcher/dispatcher";
|
|
||||||
import {
|
|
||||||
shouldShowSpaceInvite,
|
|
||||||
showAddExistingRooms,
|
|
||||||
showCreateNewRoom,
|
|
||||||
showCreateNewSubspace,
|
|
||||||
showSpaceInvite,
|
|
||||||
} from "../../../utils/space";
|
|
||||||
import { Action } from "../../../dispatcher/actions";
|
|
||||||
import { useDispatcher } from "../../../hooks/useDispatcher";
|
|
||||||
import InlineSpinner from "../elements/InlineSpinner";
|
|
||||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
|
||||||
import RoomListStore, { LISTS_UPDATE_EVENT } from "../../../stores/room-list/RoomListStore";
|
|
||||||
import {
|
import {
|
||||||
getMetaSpaceName,
|
getMetaSpaceName,
|
||||||
MetaSpace,
|
MetaSpace,
|
||||||
|
@ -50,13 +37,24 @@ import {
|
||||||
UPDATE_HOME_BEHAVIOUR,
|
UPDATE_HOME_BEHAVIOUR,
|
||||||
UPDATE_SELECTED_SPACE,
|
UPDATE_SELECTED_SPACE,
|
||||||
} from "../../../stores/spaces";
|
} from "../../../stores/spaces";
|
||||||
import TooltipTarget from "../elements/TooltipTarget";
|
import SpaceStore from "../../../stores/spaces/SpaceStore";
|
||||||
|
import {
|
||||||
|
shouldShowSpaceInvite,
|
||||||
|
showAddExistingRooms,
|
||||||
|
showCreateNewRoom,
|
||||||
|
showCreateNewSubspace,
|
||||||
|
showSpaceInvite,
|
||||||
|
} from "../../../utils/space";
|
||||||
|
import { ChevronFace, ContextMenuTooltipButton, useContextMenu } from "../../structures/ContextMenu";
|
||||||
import { BetaPill } from "../beta/BetaCard";
|
import { BetaPill } from "../beta/BetaCard";
|
||||||
import PosthogTrackers from "../../../PosthogTrackers";
|
import IconizedContextMenu, {
|
||||||
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
|
IconizedContextMenuOption,
|
||||||
import { useWebSearchMetrics } from "../dialogs/spotlight/SpotlightDialog";
|
IconizedContextMenuOptionList,
|
||||||
import { shouldShowComponent } from "../../../customisations/helpers/UIComponents";
|
} from "../context_menus/IconizedContextMenu";
|
||||||
import { UIComponent } from "../../../settings/UIFeature";
|
import SpaceContextMenu from "../context_menus/SpaceContextMenu";
|
||||||
|
import InlineSpinner from "../elements/InlineSpinner";
|
||||||
|
import TooltipTarget from "../elements/TooltipTarget";
|
||||||
|
import { HomeButtonContextMenu } from "../spaces/SpacePanel";
|
||||||
|
|
||||||
const contextMenuBelow = (elementRect: DOMRect) => {
|
const contextMenuBelow = (elementRect: DOMRect) => {
|
||||||
// align the context menu's icons with the icon which opened the context menu
|
// align the context menu's icons with the icon which opened the context menu
|
||||||
|
@ -131,15 +129,6 @@ const RoomListHeader = ({ onVisibilityChange }: IProps) => {
|
||||||
const videoRoomsEnabled = useFeatureEnabled("feature_video_rooms");
|
const videoRoomsEnabled = useFeatureEnabled("feature_video_rooms");
|
||||||
const pendingActions = usePendingActions();
|
const pendingActions = usePendingActions();
|
||||||
|
|
||||||
const filterCondition = RoomListStore.instance.getFirstNameFilterCondition();
|
|
||||||
const count = useEventEmitterState(RoomListStore.instance, LISTS_UPDATE_EVENT, () => {
|
|
||||||
if (filterCondition) {
|
|
||||||
return Object.values(RoomListStore.instance.orderedLists).flat(1).length;
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const canShowMainMenu = activeSpace || spaceKey === MetaSpace.Home;
|
const canShowMainMenu = activeSpace || spaceKey === MetaSpace.Home;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -149,22 +138,13 @@ const RoomListHeader = ({ onVisibilityChange }: IProps) => {
|
||||||
}
|
}
|
||||||
}, [closeMainMenu, canShowMainMenu, mainMenuDisplayed]);
|
}, [closeMainMenu, canShowMainMenu, mainMenuDisplayed]);
|
||||||
|
|
||||||
// we pass null for the queryLength to inhibit the metrics hook for when there is no filterCondition
|
|
||||||
useWebSearchMetrics(count, filterCondition ? filterCondition.search.length : null, false);
|
|
||||||
|
|
||||||
const spaceName = useTypedEventEmitterState(activeSpace, RoomEvent.Name, () => activeSpace?.name);
|
const spaceName = useTypedEventEmitterState(activeSpace, RoomEvent.Name, () => activeSpace?.name);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (onVisibilityChange) {
|
if (onVisibilityChange) {
|
||||||
onVisibilityChange();
|
onVisibilityChange();
|
||||||
}
|
}
|
||||||
}, [count, onVisibilityChange]);
|
}, [onVisibilityChange]);
|
||||||
|
|
||||||
if (typeof count === "number") {
|
|
||||||
return <div className="mx_LeftPanel_roomListFilterCount">
|
|
||||||
{ _t("%(count)s results", { count }) }
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const canAddRooms = activeSpace?.currentState?.maySendStateEvent(EventType.SpaceChild, cli.getUserId());
|
const canAddRooms = activeSpace?.currentState?.maySendStateEvent(EventType.SpaceChild, cli.getUserId());
|
||||||
|
|
||||||
|
|
|
@ -16,45 +16,44 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as React from "react";
|
|
||||||
import { ComponentType, createRef, ReactComponentElement } from "react";
|
|
||||||
import { normalize } from "matrix-js-sdk/src/utils";
|
|
||||||
import { Room } from "matrix-js-sdk/src/models/room";
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import { Dispatcher } from "flux";
|
||||||
|
import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
import { Enable, Resizable } from "re-resizable";
|
import { Enable, Resizable } from "re-resizable";
|
||||||
import { Direction } from "re-resizable/lib/resizer";
|
import { Direction } from "re-resizable/lib/resizer";
|
||||||
import { Dispatcher } from "flux";
|
import * as React from "react";
|
||||||
|
import { ComponentType, createRef, ReactComponentElement } from "react";
|
||||||
|
|
||||||
|
import { polyfillTouchEvent } from "../../../@types/polyfill";
|
||||||
|
import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts";
|
||||||
import { RovingAccessibleButton, RovingTabIndexWrapper } from "../../../accessibility/RovingTabIndex";
|
import { RovingAccessibleButton, RovingTabIndexWrapper } from "../../../accessibility/RovingTabIndex";
|
||||||
|
import { Action } from "../../../dispatcher/actions";
|
||||||
|
import defaultDispatcher from "../../../dispatcher/dispatcher";
|
||||||
|
import { ActionPayload } from "../../../dispatcher/payloads";
|
||||||
|
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
|
||||||
|
import { getKeyBindingsManager } from "../../../KeyBindingsManager";
|
||||||
import { _t } from "../../../languageHandler";
|
import { _t } from "../../../languageHandler";
|
||||||
import AccessibleButton from "../../views/elements/AccessibleButton";
|
import { ListNotificationState } from "../../../stores/notifications/ListNotificationState";
|
||||||
import RoomTile from "./RoomTile";
|
import { RoomNotificationStateStore } from "../../../stores/notifications/RoomNotificationStateStore";
|
||||||
|
import { ListAlgorithm, SortAlgorithm } from "../../../stores/room-list/algorithms/models";
|
||||||
import { ListLayout } from "../../../stores/room-list/ListLayout";
|
import { ListLayout } from "../../../stores/room-list/ListLayout";
|
||||||
|
import { DefaultTagID, TagID } from "../../../stores/room-list/models";
|
||||||
|
import RoomListLayoutStore from "../../../stores/room-list/RoomListLayoutStore";
|
||||||
|
import RoomListStore, { LISTS_UPDATE_EVENT } from "../../../stores/room-list/RoomListStore";
|
||||||
|
import { arrayFastClone, arrayHasOrderChange } from "../../../utils/arrays";
|
||||||
|
import { objectExcluding, objectHasDiff } from "../../../utils/objects";
|
||||||
|
import ResizeNotifier from "../../../utils/ResizeNotifier";
|
||||||
import ContextMenu, {
|
import ContextMenu, {
|
||||||
ChevronFace,
|
ChevronFace,
|
||||||
ContextMenuTooltipButton,
|
ContextMenuTooltipButton,
|
||||||
StyledMenuItemCheckbox,
|
StyledMenuItemCheckbox,
|
||||||
StyledMenuItemRadio,
|
StyledMenuItemRadio,
|
||||||
} from "../../structures/ContextMenu";
|
} from "../../structures/ContextMenu";
|
||||||
import RoomListStore, { LISTS_UPDATE_EVENT } from "../../../stores/room-list/RoomListStore";
|
import AccessibleButton from "../../views/elements/AccessibleButton";
|
||||||
import { ListAlgorithm, SortAlgorithm } from "../../../stores/room-list/algorithms/models";
|
|
||||||
import { DefaultTagID, TagID } from "../../../stores/room-list/models";
|
|
||||||
import defaultDispatcher from "../../../dispatcher/dispatcher";
|
|
||||||
import { Action } from "../../../dispatcher/actions";
|
|
||||||
import NotificationBadge from "./NotificationBadge";
|
|
||||||
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
|
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
|
||||||
import { ActionPayload } from "../../../dispatcher/payloads";
|
|
||||||
import { polyfillTouchEvent } from "../../../@types/polyfill";
|
|
||||||
import ResizeNotifier from "../../../utils/ResizeNotifier";
|
|
||||||
import { RoomNotificationStateStore } from "../../../stores/notifications/RoomNotificationStateStore";
|
|
||||||
import RoomListLayoutStore from "../../../stores/room-list/RoomListLayoutStore";
|
|
||||||
import { arrayFastClone, arrayHasOrderChange } from "../../../utils/arrays";
|
|
||||||
import { objectExcluding, objectHasDiff } from "../../../utils/objects";
|
|
||||||
import ExtraTile from "./ExtraTile";
|
import ExtraTile from "./ExtraTile";
|
||||||
import { ListNotificationState } from "../../../stores/notifications/ListNotificationState";
|
import NotificationBadge from "./NotificationBadge";
|
||||||
import { getKeyBindingsManager } from "../../../KeyBindingsManager";
|
import RoomTile from "./RoomTile";
|
||||||
import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts";
|
|
||||||
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
|
|
||||||
|
|
||||||
const SHOW_N_BUTTON_HEIGHT = 28; // As defined by CSS
|
const SHOW_N_BUTTON_HEIGHT = 28; // As defined by CSS
|
||||||
const RESIZE_HANDLE_HEIGHT = 4; // As defined by CSS
|
const RESIZE_HANDLE_HEIGHT = 4; // As defined by CSS
|
||||||
|
@ -99,7 +98,6 @@ interface IState {
|
||||||
isExpanded: boolean; // used for the for expand of the sublist when the room list is being filtered
|
isExpanded: boolean; // used for the for expand of the sublist when the room list is being filtered
|
||||||
height: number;
|
height: number;
|
||||||
rooms: Room[];
|
rooms: Room[];
|
||||||
filteredExtraTiles?: ReactComponentElement<typeof ExtraTile>[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class RoomSublist extends React.Component<IProps, IState> {
|
export default class RoomSublist extends React.Component<IProps, IState> {
|
||||||
|
@ -109,7 +107,6 @@ export default class RoomSublist extends React.Component<IProps, IState> {
|
||||||
private dispatcherRef: string;
|
private dispatcherRef: string;
|
||||||
private layout: ListLayout;
|
private layout: ListLayout;
|
||||||
private heightAtStart: number;
|
private heightAtStart: number;
|
||||||
private isBeingFiltered: boolean;
|
|
||||||
private notificationState: ListNotificationState;
|
private notificationState: ListNotificationState;
|
||||||
|
|
||||||
constructor(props: IProps) {
|
constructor(props: IProps) {
|
||||||
|
@ -117,12 +114,11 @@ export default class RoomSublist extends React.Component<IProps, IState> {
|
||||||
|
|
||||||
this.layout = RoomListLayoutStore.instance.getLayoutFor(this.props.tagId);
|
this.layout = RoomListLayoutStore.instance.getLayoutFor(this.props.tagId);
|
||||||
this.heightAtStart = 0;
|
this.heightAtStart = 0;
|
||||||
this.isBeingFiltered = !!RoomListStore.instance.getFirstNameFilterCondition();
|
|
||||||
this.notificationState = RoomNotificationStateStore.instance.getListState(this.props.tagId);
|
this.notificationState = RoomNotificationStateStore.instance.getListState(this.props.tagId);
|
||||||
this.state = {
|
this.state = {
|
||||||
contextMenuPosition: null,
|
contextMenuPosition: null,
|
||||||
isResizing: false,
|
isResizing: false,
|
||||||
isExpanded: this.isBeingFiltered ? this.isBeingFiltered : !this.layout.isCollapsed,
|
isExpanded: !this.layout.isCollapsed,
|
||||||
height: 0, // to be fixed in a moment, we need `rooms` to calculate this.
|
height: 0, // to be fixed in a moment, we need `rooms` to calculate this.
|
||||||
rooms: arrayFastClone(RoomListStore.instance.orderedLists[this.props.tagId] || []),
|
rooms: arrayFastClone(RoomListStore.instance.orderedLists[this.props.tagId] || []),
|
||||||
};
|
};
|
||||||
|
@ -156,9 +152,6 @@ export default class RoomSublist extends React.Component<IProps, IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private get extraTiles(): ReactComponentElement<typeof ExtraTile>[] | null {
|
private get extraTiles(): ReactComponentElement<typeof ExtraTile>[] | null {
|
||||||
if (this.state.filteredExtraTiles) {
|
|
||||||
return this.state.filteredExtraTiles;
|
|
||||||
}
|
|
||||||
if (this.props.extraTiles) {
|
if (this.props.extraTiles) {
|
||||||
return this.props.extraTiles;
|
return this.props.extraTiles;
|
||||||
}
|
}
|
||||||
|
@ -179,7 +172,7 @@ export default class RoomSublist extends React.Component<IProps, IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public componentDidUpdate(prevProps: Readonly<IProps>, prevState: Readonly<IState>) {
|
public componentDidUpdate(prevProps: Readonly<IProps>, prevState: Readonly<IState>) {
|
||||||
const prevExtraTiles = prevState.filteredExtraTiles || prevProps.extraTiles;
|
const prevExtraTiles = prevProps.extraTiles;
|
||||||
// as the rooms can come in one by one we need to reevaluate
|
// as the rooms can come in one by one we need to reevaluate
|
||||||
// the amount of available rooms to cap the amount of requested visible rooms by the layout
|
// the amount of available rooms to cap the amount of requested visible rooms by the layout
|
||||||
if (RoomSublist.calcNumTiles(prevState.rooms, prevExtraTiles) !== this.numTiles) {
|
if (RoomSublist.calcNumTiles(prevState.rooms, prevExtraTiles) !== this.numTiles) {
|
||||||
|
@ -203,7 +196,7 @@ export default class RoomSublist extends React.Component<IProps, IState> {
|
||||||
// If we're supposed to handle extra tiles, take the performance hit and re-render all the
|
// If we're supposed to handle extra tiles, take the performance hit and re-render all the
|
||||||
// time so we don't have to consider them as part of the visible room optimization.
|
// time so we don't have to consider them as part of the visible room optimization.
|
||||||
const prevExtraTiles = this.props.extraTiles || [];
|
const prevExtraTiles = this.props.extraTiles || [];
|
||||||
const nextExtraTiles = (nextState.filteredExtraTiles || nextProps.extraTiles) || [];
|
const nextExtraTiles = nextProps.extraTiles || [];
|
||||||
if (prevExtraTiles.length > 0 || nextExtraTiles.length > 0) {
|
if (prevExtraTiles.length > 0 || nextExtraTiles.length > 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -260,32 +253,12 @@ export default class RoomSublist extends React.Component<IProps, IState> {
|
||||||
private onListsUpdated = () => {
|
private onListsUpdated = () => {
|
||||||
const stateUpdates: IState & any = {}; // &any is to avoid a cast on the initializer
|
const stateUpdates: IState & any = {}; // &any is to avoid a cast on the initializer
|
||||||
|
|
||||||
if (this.props.extraTiles) {
|
|
||||||
const nameCondition = RoomListStore.instance.getFirstNameFilterCondition();
|
|
||||||
if (nameCondition) {
|
|
||||||
stateUpdates.filteredExtraTiles = this.props.extraTiles
|
|
||||||
.filter(t => nameCondition.matches(normalize(t.props.displayName || "")));
|
|
||||||
} else if (this.state.filteredExtraTiles) {
|
|
||||||
stateUpdates.filteredExtraTiles = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const currentRooms = this.state.rooms;
|
const currentRooms = this.state.rooms;
|
||||||
const newRooms = arrayFastClone(RoomListStore.instance.orderedLists[this.props.tagId] || []);
|
const newRooms = arrayFastClone(RoomListStore.instance.orderedLists[this.props.tagId] || []);
|
||||||
if (arrayHasOrderChange(currentRooms, newRooms)) {
|
if (arrayHasOrderChange(currentRooms, newRooms)) {
|
||||||
stateUpdates.rooms = newRooms;
|
stateUpdates.rooms = newRooms;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isStillBeingFiltered = !!RoomListStore.instance.getFirstNameFilterCondition();
|
|
||||||
if (isStillBeingFiltered !== this.isBeingFiltered) {
|
|
||||||
this.isBeingFiltered = isStillBeingFiltered;
|
|
||||||
if (isStillBeingFiltered) {
|
|
||||||
stateUpdates.isExpanded = true;
|
|
||||||
} else {
|
|
||||||
stateUpdates.isExpanded = !this.layout.isCollapsed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Object.keys(stateUpdates).length > 0) {
|
if (Object.keys(stateUpdates).length > 0) {
|
||||||
this.setState(stateUpdates);
|
this.setState(stateUpdates);
|
||||||
}
|
}
|
||||||
|
@ -418,7 +391,7 @@ export default class RoomSublist extends React.Component<IProps, IState> {
|
||||||
room = this.state.rooms && this.state.rooms[0];
|
room = this.state.rooms && this.state.rooms[0];
|
||||||
} else {
|
} else {
|
||||||
// find the first room with a count of the same colour as the badge count
|
// find the first room with a count of the same colour as the badge count
|
||||||
room = RoomListStore.instance.unfilteredLists[this.props.tagId].find((r: Room) => {
|
room = RoomListStore.instance.orderedLists[this.props.tagId].find((r: Room) => {
|
||||||
const notifState = this.notificationState.getForRoom(r);
|
const notifState = this.notificationState.getForRoom(r);
|
||||||
return notifState.count > 0 && notifState.color === this.notificationState.color;
|
return notifState.count > 0 && notifState.color === this.notificationState.color;
|
||||||
});
|
});
|
||||||
|
|
|
@ -1791,11 +1791,6 @@
|
||||||
"Historical": "Historical",
|
"Historical": "Historical",
|
||||||
"Suggested Rooms": "Suggested Rooms",
|
"Suggested Rooms": "Suggested Rooms",
|
||||||
"Empty room": "Empty room",
|
"Empty room": "Empty room",
|
||||||
"Can't see what you're looking for?": "Can't see what you're looking for?",
|
|
||||||
"Start a new chat": "Start a new chat",
|
|
||||||
"Explore all public rooms": "Explore all public rooms",
|
|
||||||
"%(count)s results|other": "%(count)s results",
|
|
||||||
"%(count)s results|one": "%(count)s result",
|
|
||||||
"Add space": "Add space",
|
"Add space": "Add space",
|
||||||
"You do not have permissions to add spaces to this space": "You do not have permissions to add spaces to this space",
|
"You do not have permissions to add spaces to this space": "You do not have permissions to add spaces to this space",
|
||||||
"Join public room": "Join public room",
|
"Join public room": "Join public room",
|
||||||
|
|
|
@ -26,14 +26,13 @@ import { IListOrderingMap, ITagMap, ITagSortingMap, ListAlgorithm, SortAlgorithm
|
||||||
import { ActionPayload } from "../../dispatcher/payloads";
|
import { ActionPayload } from "../../dispatcher/payloads";
|
||||||
import defaultDispatcher from "../../dispatcher/dispatcher";
|
import defaultDispatcher from "../../dispatcher/dispatcher";
|
||||||
import { readReceiptChangeIsFor } from "../../utils/read-receipts";
|
import { readReceiptChangeIsFor } from "../../utils/read-receipts";
|
||||||
import { FILTER_CHANGED, FilterKind, IFilterCondition } from "./filters/IFilterCondition";
|
import { FILTER_CHANGED, IFilterCondition } from "./filters/IFilterCondition";
|
||||||
import { RoomViewStore } from "../RoomViewStore";
|
import { RoomViewStore } from "../RoomViewStore";
|
||||||
import { Algorithm, LIST_UPDATED_EVENT } from "./algorithms/Algorithm";
|
import { Algorithm, LIST_UPDATED_EVENT } from "./algorithms/Algorithm";
|
||||||
import { EffectiveMembership, getEffectiveMembership } from "../../utils/membership";
|
import { EffectiveMembership, getEffectiveMembership } from "../../utils/membership";
|
||||||
import RoomListLayoutStore from "./RoomListLayoutStore";
|
import RoomListLayoutStore from "./RoomListLayoutStore";
|
||||||
import { MarkedExecution } from "../../utils/MarkedExecution";
|
import { MarkedExecution } from "../../utils/MarkedExecution";
|
||||||
import { AsyncStoreWithClient } from "../AsyncStoreWithClient";
|
import { AsyncStoreWithClient } from "../AsyncStoreWithClient";
|
||||||
import { NameFilterCondition } from "./filters/NameFilterCondition";
|
|
||||||
import { RoomNotificationStateStore } from "../notifications/RoomNotificationStateStore";
|
import { RoomNotificationStateStore } from "../notifications/RoomNotificationStateStore";
|
||||||
import { VisibilityProvider } from "./filters/VisibilityProvider";
|
import { VisibilityProvider } from "./filters/VisibilityProvider";
|
||||||
import { SpaceWatcher } from "./SpaceWatcher";
|
import { SpaceWatcher } from "./SpaceWatcher";
|
||||||
|
@ -58,7 +57,6 @@ export class RoomListStoreClass extends AsyncStoreWithClient<IState> {
|
||||||
|
|
||||||
private initialListsGenerated = false;
|
private initialListsGenerated = false;
|
||||||
private algorithm = new Algorithm();
|
private algorithm = new Algorithm();
|
||||||
private filterConditions: IFilterCondition[] = [];
|
|
||||||
private prefilterConditions: IFilterCondition[] = [];
|
private prefilterConditions: IFilterCondition[] = [];
|
||||||
private updateFn = new MarkedExecution(() => {
|
private updateFn = new MarkedExecution(() => {
|
||||||
for (const tagId of Object.keys(this.orderedLists)) {
|
for (const tagId of Object.keys(this.orderedLists)) {
|
||||||
|
@ -78,11 +76,6 @@ export class RoomListStoreClass extends AsyncStoreWithClient<IState> {
|
||||||
new SpaceWatcher(this);
|
new SpaceWatcher(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public get unfilteredLists(): ITagMap {
|
|
||||||
if (!this.algorithm) return {}; // No tags yet.
|
|
||||||
return this.algorithm.getUnfilteredRooms();
|
|
||||||
}
|
|
||||||
|
|
||||||
public get orderedLists(): ITagMap {
|
public get orderedLists(): ITagMap {
|
||||||
if (!this.algorithm) return {}; // No tags yet.
|
if (!this.algorithm) return {}; // No tags yet.
|
||||||
return this.algorithm.getOrderedRooms();
|
return this.algorithm.getOrderedRooms();
|
||||||
|
@ -91,7 +84,6 @@ export class RoomListStoreClass extends AsyncStoreWithClient<IState> {
|
||||||
// Intended for test usage
|
// Intended for test usage
|
||||||
public async resetStore() {
|
public async resetStore() {
|
||||||
await this.reset();
|
await this.reset();
|
||||||
this.filterConditions = [];
|
|
||||||
this.prefilterConditions = [];
|
this.prefilterConditions = [];
|
||||||
this.initialListsGenerated = false;
|
this.initialListsGenerated = false;
|
||||||
|
|
||||||
|
@ -502,9 +494,7 @@ export class RoomListStoreClass extends AsyncStoreWithClient<IState> {
|
||||||
|
|
||||||
let rooms = this.matrixClient.getVisibleRooms().filter(r => VisibilityProvider.instance.isRoomVisible(r));
|
let rooms = this.matrixClient.getVisibleRooms().filter(r => VisibilityProvider.instance.isRoomVisible(r));
|
||||||
|
|
||||||
// if spaces are enabled only consider the prefilter conditions when there are no runtime conditions
|
if (this.prefilterConditions.length > 0) {
|
||||||
// for the search all spaces feature
|
|
||||||
if (this.prefilterConditions.length > 0 && !this.filterConditions.length) {
|
|
||||||
rooms = rooms.filter(r => {
|
rooms = rooms.filter(r => {
|
||||||
for (const filter of this.prefilterConditions) {
|
for (const filter of this.prefilterConditions) {
|
||||||
if (!filter.isVisible(r)) {
|
if (!filter.isVisible(r)) {
|
||||||
|
@ -556,20 +546,9 @@ export class RoomListStoreClass extends AsyncStoreWithClient<IState> {
|
||||||
*/
|
*/
|
||||||
public async addFilter(filter: IFilterCondition): Promise<void> {
|
public async addFilter(filter: IFilterCondition): Promise<void> {
|
||||||
let promise = Promise.resolve();
|
let promise = Promise.resolve();
|
||||||
if (filter.kind === FilterKind.Prefilter) {
|
|
||||||
filter.on(FILTER_CHANGED, this.onPrefilterUpdated);
|
filter.on(FILTER_CHANGED, this.onPrefilterUpdated);
|
||||||
this.prefilterConditions.push(filter);
|
this.prefilterConditions.push(filter);
|
||||||
promise = this.recalculatePrefiltering();
|
promise = this.recalculatePrefiltering();
|
||||||
} else {
|
|
||||||
this.filterConditions.push(filter);
|
|
||||||
// Runtime filters with spaces disable prefiltering for the search all spaces feature.
|
|
||||||
// this has to be awaited so that `setKnownRooms` is called in time for the `addFilterCondition` below
|
|
||||||
// this way the runtime filters are only evaluated on one dataset and not both.
|
|
||||||
await this.recalculatePrefiltering();
|
|
||||||
if (this.algorithm) {
|
|
||||||
this.algorithm.addFilterCondition(filter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
promise.then(() => this.updateFn.trigger());
|
promise.then(() => this.updateFn.trigger());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -582,20 +561,8 @@ export class RoomListStoreClass extends AsyncStoreWithClient<IState> {
|
||||||
*/
|
*/
|
||||||
public removeFilter(filter: IFilterCondition): void {
|
public removeFilter(filter: IFilterCondition): void {
|
||||||
let promise = Promise.resolve();
|
let promise = Promise.resolve();
|
||||||
let idx = this.filterConditions.indexOf(filter);
|
|
||||||
let removed = false;
|
let removed = false;
|
||||||
if (idx >= 0) {
|
const idx = this.prefilterConditions.indexOf(filter);
|
||||||
this.filterConditions.splice(idx, 1);
|
|
||||||
|
|
||||||
if (this.algorithm) {
|
|
||||||
this.algorithm.removeFilterCondition(filter);
|
|
||||||
}
|
|
||||||
// Runtime filters with spaces disable prefiltering for the search all spaces feature
|
|
||||||
promise = this.recalculatePrefiltering();
|
|
||||||
removed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
idx = this.prefilterConditions.indexOf(filter);
|
|
||||||
if (idx >= 0) {
|
if (idx >= 0) {
|
||||||
filter.off(FILTER_CHANGED, this.onPrefilterUpdated);
|
filter.off(FILTER_CHANGED, this.onPrefilterUpdated);
|
||||||
this.prefilterConditions.splice(idx, 1);
|
this.prefilterConditions.splice(idx, 1);
|
||||||
|
@ -608,20 +575,6 @@ export class RoomListStoreClass extends AsyncStoreWithClient<IState> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the first (and ideally only) name filter condition. If one isn't present,
|
|
||||||
* this returns null.
|
|
||||||
* @returns The first name filter condition, or null if none.
|
|
||||||
*/
|
|
||||||
public getFirstNameFilterCondition(): NameFilterCondition | null {
|
|
||||||
for (const filter of this.filterConditions) {
|
|
||||||
if (filter instanceof NameFilterCondition) {
|
|
||||||
return filter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the tags for a room identified by the store. The returned set
|
* Gets the tags for a room identified by the store. The returned set
|
||||||
* should never be empty, and will contain DefaultTagID.Untagged if
|
* should never be empty, and will contain DefaultTagID.Untagged if
|
||||||
|
|
|
@ -30,7 +30,6 @@ import {
|
||||||
ListAlgorithm,
|
ListAlgorithm,
|
||||||
SortAlgorithm,
|
SortAlgorithm,
|
||||||
} from "./models";
|
} from "./models";
|
||||||
import { FILTER_CHANGED, IFilterCondition } from "../filters/IFilterCondition";
|
|
||||||
import { EffectiveMembership, getEffectiveMembership, splitRoomsByMembership } from "../../../utils/membership";
|
import { EffectiveMembership, getEffectiveMembership, splitRoomsByMembership } from "../../../utils/membership";
|
||||||
import { OrderingAlgorithm } from "./list-ordering/OrderingAlgorithm";
|
import { OrderingAlgorithm } from "./list-ordering/OrderingAlgorithm";
|
||||||
import { getListAlgorithmInstance } from "./list-ordering";
|
import { getListAlgorithmInstance } from "./list-ordering";
|
||||||
|
@ -67,7 +66,6 @@ interface IStickyRoom {
|
||||||
export class Algorithm extends EventEmitter {
|
export class Algorithm extends EventEmitter {
|
||||||
private _cachedRooms: ITagMap = {};
|
private _cachedRooms: ITagMap = {};
|
||||||
private _cachedStickyRooms: ITagMap = {}; // a clone of the _cachedRooms, with the sticky room
|
private _cachedStickyRooms: ITagMap = {}; // a clone of the _cachedRooms, with the sticky room
|
||||||
private filteredRooms: ITagMap = {};
|
|
||||||
private _stickyRoom: IStickyRoom = null;
|
private _stickyRoom: IStickyRoom = null;
|
||||||
private _lastStickyRoom: IStickyRoom = null; // only not-null when changing the sticky room
|
private _lastStickyRoom: IStickyRoom = null; // only not-null when changing the sticky room
|
||||||
private sortAlgorithms: ITagSortingMap;
|
private sortAlgorithms: ITagSortingMap;
|
||||||
|
@ -77,8 +75,6 @@ export class Algorithm extends EventEmitter {
|
||||||
private roomIdsToTags: {
|
private roomIdsToTags: {
|
||||||
[roomId: string]: TagID[];
|
[roomId: string]: TagID[];
|
||||||
} = {};
|
} = {};
|
||||||
private allowedByFilter: Map<IFilterCondition, Room[]> = new Map<IFilterCondition, Room[]>();
|
|
||||||
private allowedRoomsByFilters: Set<Room> = new Set<Room>();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set to true to suspend emissions of algorithm updates.
|
* Set to true to suspend emissions of algorithm updates.
|
||||||
|
@ -107,13 +103,8 @@ export class Algorithm extends EventEmitter {
|
||||||
return !!this.sortAlgorithms;
|
return !!this.sortAlgorithms;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected get hasFilters(): boolean {
|
|
||||||
return this.allowedByFilter.size > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected set cachedRooms(val: ITagMap) {
|
protected set cachedRooms(val: ITagMap) {
|
||||||
this._cachedRooms = val;
|
this._cachedRooms = val;
|
||||||
this.recalculateFilteredRooms();
|
|
||||||
this.recalculateStickyRoom();
|
this.recalculateStickyRoom();
|
||||||
this.recalculateVideoRoom();
|
this.recalculateVideoRoom();
|
||||||
}
|
}
|
||||||
|
@ -151,7 +142,6 @@ export class Algorithm extends EventEmitter {
|
||||||
const algorithm: OrderingAlgorithm = this.algorithms[tagId];
|
const algorithm: OrderingAlgorithm = this.algorithms[tagId];
|
||||||
algorithm.setSortAlgorithm(sort);
|
algorithm.setSortAlgorithm(sort);
|
||||||
this._cachedRooms[tagId] = algorithm.orderedRooms;
|
this._cachedRooms[tagId] = algorithm.orderedRooms;
|
||||||
this.recalculateFilteredRoomsForTag(tagId); // update filter to re-sort the list
|
|
||||||
this.recalculateStickyRoom(tagId); // update sticky room to make sure it appears if needed
|
this.recalculateStickyRoom(tagId); // update sticky room to make sure it appears if needed
|
||||||
this.recalculateVideoRoom(tagId);
|
this.recalculateVideoRoom(tagId);
|
||||||
}
|
}
|
||||||
|
@ -171,40 +161,10 @@ export class Algorithm extends EventEmitter {
|
||||||
|
|
||||||
algorithm.setRooms(this._cachedRooms[tagId]);
|
algorithm.setRooms(this._cachedRooms[tagId]);
|
||||||
this._cachedRooms[tagId] = algorithm.orderedRooms;
|
this._cachedRooms[tagId] = algorithm.orderedRooms;
|
||||||
this.recalculateFilteredRoomsForTag(tagId); // update filter to re-sort the list
|
|
||||||
this.recalculateStickyRoom(tagId); // update sticky room to make sure it appears if needed
|
this.recalculateStickyRoom(tagId); // update sticky room to make sure it appears if needed
|
||||||
this.recalculateVideoRoom(tagId);
|
this.recalculateVideoRoom(tagId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public addFilterCondition(filterCondition: IFilterCondition): void {
|
|
||||||
// Populate the cache of the new filter
|
|
||||||
this.allowedByFilter.set(filterCondition, this.rooms.filter(r => filterCondition.isVisible(r)));
|
|
||||||
this.recalculateFilteredRooms();
|
|
||||||
filterCondition.on(FILTER_CHANGED, this.handleFilterChange.bind(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
public removeFilterCondition(filterCondition: IFilterCondition): void {
|
|
||||||
filterCondition.off(FILTER_CHANGED, this.handleFilterChange.bind(this));
|
|
||||||
if (this.allowedByFilter.has(filterCondition)) {
|
|
||||||
this.allowedByFilter.delete(filterCondition);
|
|
||||||
this.recalculateFilteredRooms();
|
|
||||||
|
|
||||||
// If we removed the last filter, tell consumers that we've "updated" our filtered
|
|
||||||
// view. This will trick them into getting the complete room list.
|
|
||||||
if (!this.hasFilters && !this.updatesInhibited) {
|
|
||||||
this.emit(LIST_UPDATED_EVENT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private handleFilterChange() {
|
|
||||||
this.recalculateFilteredRooms();
|
|
||||||
|
|
||||||
// re-emit the update so the list store can fire an off-cycle update if needed
|
|
||||||
if (this.updatesInhibited) return;
|
|
||||||
this.emit(FILTER_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
private updateStickyRoom(val: Room) {
|
private updateStickyRoom(val: Room) {
|
||||||
this.doUpdateStickyRoom(val);
|
this.doUpdateStickyRoom(val);
|
||||||
this._lastStickyRoom = null; // clear to indicate we're done changing
|
this._lastStickyRoom = null; // clear to indicate we're done changing
|
||||||
|
@ -318,8 +278,6 @@ export class Algorithm extends EventEmitter {
|
||||||
// We update the filtered rooms just in case, as otherwise users will end up visiting
|
// We update the filtered rooms just in case, as otherwise users will end up visiting
|
||||||
// a room while filtering and it'll disappear. We don't update the filter earlier in
|
// a room while filtering and it'll disappear. We don't update the filter earlier in
|
||||||
// this function simply because we don't have to.
|
// this function simply because we don't have to.
|
||||||
this.recalculateFilteredRoomsForTag(tag);
|
|
||||||
if (lastStickyRoom && lastStickyRoom.tag !== tag) this.recalculateFilteredRoomsForTag(lastStickyRoom.tag);
|
|
||||||
this.recalculateStickyRoom();
|
this.recalculateStickyRoom();
|
||||||
this.recalculateVideoRoom(tag);
|
this.recalculateVideoRoom(tag);
|
||||||
if (lastStickyRoom && lastStickyRoom.tag !== tag) this.recalculateVideoRoom(lastStickyRoom.tag);
|
if (lastStickyRoom && lastStickyRoom.tag !== tag) this.recalculateVideoRoom(lastStickyRoom.tag);
|
||||||
|
@ -334,7 +292,6 @@ export class Algorithm extends EventEmitter {
|
||||||
*/
|
*/
|
||||||
public updateVideoRoom = () => {
|
public updateVideoRoom = () => {
|
||||||
// In case we're unsticking a video room, sort it back into natural order
|
// In case we're unsticking a video room, sort it back into natural order
|
||||||
this.recalculateFilteredRooms();
|
|
||||||
this.recalculateStickyRoom();
|
this.recalculateStickyRoom();
|
||||||
|
|
||||||
this.recalculateVideoRoom();
|
this.recalculateVideoRoom();
|
||||||
|
@ -345,63 +302,6 @@ export class Algorithm extends EventEmitter {
|
||||||
this.emit(LIST_UPDATED_EVENT, true);
|
this.emit(LIST_UPDATED_EVENT, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
protected recalculateFilteredRooms() {
|
|
||||||
if (!this.hasFilters) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.warn("Recalculating filtered room list");
|
|
||||||
const filters = Array.from(this.allowedByFilter.keys());
|
|
||||||
const newMap: ITagMap = {};
|
|
||||||
for (const tagId of Object.keys(this.cachedRooms)) {
|
|
||||||
// Cheaply clone the rooms so we can more easily do operations on the list.
|
|
||||||
// We optimize our lookups by trying to reduce sample size as much as possible
|
|
||||||
// to the rooms we know will be deduped by the Set.
|
|
||||||
const rooms = this.cachedRooms[tagId].map(r => r); // cheap clone
|
|
||||||
this.tryInsertStickyRoomToFilterSet(rooms, tagId);
|
|
||||||
const remainingRooms = rooms.map(r => r);
|
|
||||||
const allowedRoomsInThisTag = [];
|
|
||||||
for (const filter of filters) {
|
|
||||||
const filteredRooms = remainingRooms.filter(r => filter.isVisible(r));
|
|
||||||
for (const room of filteredRooms) {
|
|
||||||
const idx = remainingRooms.indexOf(room);
|
|
||||||
if (idx >= 0) remainingRooms.splice(idx, 1);
|
|
||||||
allowedRoomsInThisTag.push(room);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
newMap[tagId] = allowedRoomsInThisTag;
|
|
||||||
}
|
|
||||||
|
|
||||||
const allowedRooms = Object.values(newMap).reduce((rv, v) => { rv.push(...v); return rv; }, <Room[]>[]);
|
|
||||||
this.allowedRoomsByFilters = new Set(allowedRooms);
|
|
||||||
this.filteredRooms = newMap;
|
|
||||||
if (this.updatesInhibited) return;
|
|
||||||
this.emit(LIST_UPDATED_EVENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected recalculateFilteredRoomsForTag(tagId: TagID): void {
|
|
||||||
if (!this.hasFilters) return; // don't bother doing work if there's nothing to do
|
|
||||||
|
|
||||||
delete this.filteredRooms[tagId];
|
|
||||||
const rooms = this.cachedRooms[tagId].map(r => r); // cheap clone
|
|
||||||
this.tryInsertStickyRoomToFilterSet(rooms, tagId);
|
|
||||||
const filteredRooms = rooms.filter(r => this.allowedRoomsByFilters.has(r));
|
|
||||||
if (filteredRooms.length > 0) {
|
|
||||||
this.filteredRooms[tagId] = filteredRooms;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected tryInsertStickyRoomToFilterSet(rooms: Room[], tagId: TagID) {
|
|
||||||
if (!this._stickyRoom || !this._stickyRoom.room || this._stickyRoom.tag !== tagId) return;
|
|
||||||
|
|
||||||
const position = this._stickyRoom.position;
|
|
||||||
if (position >= rooms.length) {
|
|
||||||
rooms.push(this._stickyRoom.room);
|
|
||||||
} else {
|
|
||||||
rooms.splice(position, 0, this._stickyRoom.room);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private initCachedStickyRooms() {
|
private initCachedStickyRooms() {
|
||||||
this._cachedStickyRooms = {};
|
this._cachedStickyRooms = {};
|
||||||
for (const tagId of Object.keys(this.cachedRooms)) {
|
for (const tagId of Object.keys(this.cachedRooms)) {
|
||||||
|
@ -520,18 +420,11 @@ export class Algorithm extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an ordered set of rooms for the all known tags, filtered.
|
* Gets an ordered set of rooms for the all known tags.
|
||||||
* @returns {ITagMap} The cached list of rooms, ordered,
|
* @returns {ITagMap} The cached list of rooms, ordered,
|
||||||
* for each tag. May be empty, but never null/undefined.
|
* for each tag. May be empty, but never null/undefined.
|
||||||
*/
|
*/
|
||||||
public getOrderedRooms(): ITagMap {
|
public getOrderedRooms(): ITagMap {
|
||||||
if (!this.hasFilters) {
|
|
||||||
return this._cachedStickyRooms || this.cachedRooms;
|
|
||||||
}
|
|
||||||
return this.filteredRooms;
|
|
||||||
}
|
|
||||||
|
|
||||||
public getUnfilteredRooms(): ITagMap {
|
|
||||||
return this._cachedStickyRooms || this.cachedRooms;
|
return this._cachedStickyRooms || this.cachedRooms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -543,11 +436,8 @@ export class Algorithm extends EventEmitter {
|
||||||
* for each tag. May be empty, but never null/undefined.
|
* for each tag. May be empty, but never null/undefined.
|
||||||
*/
|
*/
|
||||||
private getOrderedRoomsWithoutSticky(): ITagMap {
|
private getOrderedRoomsWithoutSticky(): ITagMap {
|
||||||
if (!this.hasFilters) {
|
|
||||||
return this.cachedRooms;
|
return this.cachedRooms;
|
||||||
}
|
}
|
||||||
return this.filteredRooms;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Seeds the Algorithm with a set of rooms. The algorithm will discard all
|
* Seeds the Algorithm with a set of rooms. The algorithm will discard all
|
||||||
|
@ -775,7 +665,6 @@ export class Algorithm extends EventEmitter {
|
||||||
if (!algorithm) throw new Error(`No algorithm for ${rmTag}`);
|
if (!algorithm) throw new Error(`No algorithm for ${rmTag}`);
|
||||||
algorithm.handleRoomUpdate(room, RoomUpdateCause.RoomRemoved);
|
algorithm.handleRoomUpdate(room, RoomUpdateCause.RoomRemoved);
|
||||||
this._cachedRooms[rmTag] = algorithm.orderedRooms;
|
this._cachedRooms[rmTag] = algorithm.orderedRooms;
|
||||||
this.recalculateFilteredRoomsForTag(rmTag); // update filter to re-sort the list
|
|
||||||
this.recalculateStickyRoom(rmTag); // update sticky room to make sure it moves if needed
|
this.recalculateStickyRoom(rmTag); // update sticky room to make sure it moves if needed
|
||||||
this.recalculateVideoRoom(rmTag);
|
this.recalculateVideoRoom(rmTag);
|
||||||
}
|
}
|
||||||
|
@ -852,7 +741,6 @@ export class Algorithm extends EventEmitter {
|
||||||
this._cachedRooms[tag] = algorithm.orderedRooms;
|
this._cachedRooms[tag] = algorithm.orderedRooms;
|
||||||
|
|
||||||
// Flag that we've done something
|
// Flag that we've done something
|
||||||
this.recalculateFilteredRoomsForTag(tag); // update filter to re-sort the list
|
|
||||||
this.recalculateStickyRoom(tag); // update sticky room to make sure it appears if needed
|
this.recalculateStickyRoom(tag); // update sticky room to make sure it appears if needed
|
||||||
this.recalculateVideoRoom(tag);
|
this.recalculateVideoRoom(tag);
|
||||||
changed = true;
|
changed = true;
|
||||||
|
|
|
@ -19,21 +19,6 @@ import { EventEmitter } from "events";
|
||||||
|
|
||||||
export const FILTER_CHANGED = "filter_changed";
|
export const FILTER_CHANGED = "filter_changed";
|
||||||
|
|
||||||
export enum FilterKind {
|
|
||||||
/**
|
|
||||||
* A prefilter is one which coarsely determines which rooms are
|
|
||||||
* available for runtime filtering/rendering. Typically this will
|
|
||||||
* be things like Space selection.
|
|
||||||
*/
|
|
||||||
Prefilter,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runtime filters operate on the data set exposed by prefilters.
|
|
||||||
* Typically these are dynamic values like room name searching.
|
|
||||||
*/
|
|
||||||
Runtime,
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A filter condition for the room list, determining if a room
|
* A filter condition for the room list, determining if a room
|
||||||
* should be shown or not.
|
* should be shown or not.
|
||||||
|
@ -47,11 +32,6 @@ export enum FilterKind {
|
||||||
* as a change in the user's input), this emits FILTER_CHANGED.
|
* as a change in the user's input), this emits FILTER_CHANGED.
|
||||||
*/
|
*/
|
||||||
export interface IFilterCondition extends EventEmitter {
|
export interface IFilterCondition extends EventEmitter {
|
||||||
/**
|
|
||||||
* The kind of filter this presents.
|
|
||||||
*/
|
|
||||||
kind: FilterKind;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if a given room should be visible under this
|
* Determines if a given room should be visible under this
|
||||||
* condition.
|
* condition.
|
||||||
|
|
|
@ -1,72 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2020, 2021 The Matrix.org Foundation C.I.C.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { Room } from "matrix-js-sdk/src/models/room";
|
|
||||||
import { EventEmitter } from "events";
|
|
||||||
import { normalize } from "matrix-js-sdk/src/utils";
|
|
||||||
import { throttle } from "lodash";
|
|
||||||
|
|
||||||
import { FILTER_CHANGED, FilterKind, IFilterCondition } from "./IFilterCondition";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A filter condition for the room list which reveals rooms of a particular
|
|
||||||
* name, or associated name (like a room alias).
|
|
||||||
*/
|
|
||||||
export class NameFilterCondition extends EventEmitter implements IFilterCondition {
|
|
||||||
private _search = "";
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public get kind(): FilterKind {
|
|
||||||
return FilterKind.Runtime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get search(): string {
|
|
||||||
return this._search;
|
|
||||||
}
|
|
||||||
|
|
||||||
public set search(val: string) {
|
|
||||||
this._search = val;
|
|
||||||
this.callUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
private callUpdate = throttle(() => {
|
|
||||||
this.emit(FILTER_CHANGED);
|
|
||||||
}, 200, { trailing: true, leading: true });
|
|
||||||
|
|
||||||
public isVisible(room: Room): boolean {
|
|
||||||
const lcFilter = this.search.toLowerCase();
|
|
||||||
if (this.search[0] === '#') {
|
|
||||||
// Try and find rooms by alias
|
|
||||||
if (room.getCanonicalAlias() && room.getCanonicalAlias().toLowerCase().startsWith(lcFilter)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (room.getAltAliases().some(a => a.toLowerCase().startsWith(lcFilter))) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!room.name) return false; // should realistically not happen: the js-sdk always calculates a name
|
|
||||||
|
|
||||||
return this.matches(room.normalizedName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public matches(normalizedName: string): boolean {
|
|
||||||
return normalizedName.includes(normalize(this.search));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -17,7 +17,7 @@ limitations under the License.
|
||||||
import { EventEmitter } from "events";
|
import { EventEmitter } from "events";
|
||||||
import { Room } from "matrix-js-sdk/src/models/room";
|
import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
|
|
||||||
import { FILTER_CHANGED, FilterKind, IFilterCondition } from "./IFilterCondition";
|
import { FILTER_CHANGED, IFilterCondition } from "./IFilterCondition";
|
||||||
import { IDestroyable } from "../../../utils/IDestroyable";
|
import { IDestroyable } from "../../../utils/IDestroyable";
|
||||||
import SpaceStore from "../../spaces/SpaceStore";
|
import SpaceStore from "../../spaces/SpaceStore";
|
||||||
import { isMetaSpace, MetaSpace, SpaceKey } from "../../spaces";
|
import { isMetaSpace, MetaSpace, SpaceKey } from "../../spaces";
|
||||||
|
@ -36,10 +36,6 @@ export class SpaceFilterCondition extends EventEmitter implements IFilterConditi
|
||||||
private showPeopleInSpace = true;
|
private showPeopleInSpace = true;
|
||||||
private space: SpaceKey = MetaSpace.Home;
|
private space: SpaceKey = MetaSpace.Home;
|
||||||
|
|
||||||
public get kind(): FilterKind {
|
|
||||||
return FilterKind.Prefilter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public isVisible(room: Room): boolean {
|
public isVisible(room: Room): boolean {
|
||||||
return SpaceStore.instance.isRoomInSpace(this.space, room.roomId);
|
return SpaceStore.instance.isRoomInSpace(this.space, room.roomId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -187,7 +187,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
|
||||||
metricsTrigger: "WebSpacePanelNotificationBadge",
|
metricsTrigger: "WebSpacePanelNotificationBadge",
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const lists = RoomListStore.instance.unfilteredLists;
|
const lists = RoomListStore.instance.orderedLists;
|
||||||
for (let i = 0; i < TAG_ORDER.length; i++) {
|
for (let i = 0; i < TAG_ORDER.length; i++) {
|
||||||
const t = TAG_ORDER[i];
|
const t = TAG_ORDER[i];
|
||||||
const listRooms = lists[t];
|
const listRooms = lists[t];
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue