mirror of https://github.com/vector-im/riot-web
				
				
				
			Remove unused code left over from the old search (#8947)
							parent
							
								
									424d33d4b0
								
							
						
					
					
						commit
						328d7ea5eb
					
				|  | @ -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 { | ||||
|             // Make the y-scrollbar more responsive | ||||
|             padding-right: 2px; | ||||
|  |  | |||
|  | @ -14,35 +14,30 @@ See the License for the specific language governing permissions and | |||
| 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 { 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 ResizeNotifier from "../../../utils/ResizeNotifier"; | ||||
| import RoomListStore, { LISTS_UPDATE_EVENT } from "../../../stores/room-list/RoomListStore"; | ||||
| import { RoomViewStore } from "../../../stores/RoomViewStore"; | ||||
| import MatrixClientContext from "../../../contexts/MatrixClientContext"; | ||||
| import { shouldShowComponent } from "../../../customisations/helpers/UIComponents"; | ||||
| 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 { DefaultTagID, TagID } from "../../../stores/room-list/models"; | ||||
| import defaultDispatcher from "../../../dispatcher/dispatcher"; | ||||
| import RoomSublist, { IAuxButtonProps } from "./RoomSublist"; | ||||
| 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 RoomListStore, { LISTS_UPDATE_EVENT } from "../../../stores/room-list/RoomListStore"; | ||||
| import { RoomViewStore } from "../../../stores/RoomViewStore"; | ||||
| import { | ||||
|     isMetaSpace, | ||||
|     ISuggestedRoom, | ||||
|  | @ -51,17 +46,21 @@ import { | |||
|     UPDATE_SELECTED_SPACE, | ||||
|     UPDATE_SUGGESTED_ROOMS, | ||||
| } 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 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 MatrixClientContext from "../../../contexts/MatrixClientContext"; | ||||
| import SettingsStore from "../../../settings/SettingsStore"; | ||||
| import PosthogTrackers from "../../../PosthogTrackers"; | ||||
| import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload"; | ||||
| import RoomAvatar from "../avatars/RoomAvatar"; | ||||
| import { BetaPill } from "../beta/BetaCard"; | ||||
| import IconizedContextMenu, { | ||||
|     IconizedContextMenuOption, | ||||
|     IconizedContextMenuOptionList, | ||||
| } from "../context_menus/IconizedContextMenu"; | ||||
| import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; | ||||
| import ExtraTile from "./ExtraTile"; | ||||
| import RoomSublist, { IAuxButtonProps } from "./RoomSublist"; | ||||
| 
 | ||||
| interface IProps { | ||||
|     onKeyDown: (ev: React.KeyboardEvent, state: IRovingTabIndexState) => void; | ||||
|  | @ -76,7 +75,6 @@ interface IProps { | |||
| 
 | ||||
| interface IState { | ||||
|     sublists: ITagMap; | ||||
|     isNameFiltering: boolean; | ||||
|     currentRoomId?: string; | ||||
|     suggestedRooms: ISuggestedRoom[]; | ||||
| } | ||||
|  | @ -403,7 +401,6 @@ export default class RoomList extends React.PureComponent<IProps, IState> { | |||
| 
 | ||||
|         this.state = { | ||||
|             sublists: {}, | ||||
|             isNameFiltering: !!RoomListStore.instance.getFirstNameFilterCondition(), | ||||
|             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 newListIds = Object.keys(newLists); | ||||
| 
 | ||||
|         const isNameFiltering = !!RoomListStore.instance.getFirstNameFilterCondition(); | ||||
|         let doUpdate = this.state.isNameFiltering !== isNameFiltering || arrayHasDiff(previousListIds, newListIds); | ||||
|         let doUpdate = arrayHasDiff(previousListIds, newListIds); | ||||
|         if (!doUpdate) { | ||||
|             // 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
 | ||||
|  | @ -503,33 +499,12 @@ export default class RoomList extends React.PureComponent<IProps, IState> { | |||
|             const newSublists = objectWithOnly(newLists, newListIds); | ||||
|             const sublists = objectShallowClone(newSublists, (k, v) => arrayFastClone(v)); | ||||
| 
 | ||||
|             this.setState({ sublists, isNameFiltering }, () => { | ||||
|             this.setState({ sublists }, () => { | ||||
|                 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>[] { | ||||
|         return this.state.suggestedRooms.map(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[] { | ||||
|         // 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 && | ||||
|             Object.values(RoomListStore.instance.unfilteredLists).every(list => !list?.length); | ||||
|         const showSkeleton = !this.state.suggestedRooms?.length && | ||||
|             Object.values(RoomListStore.instance.orderedLists).every(list => !list?.length); | ||||
| 
 | ||||
|         return TAG_ORDER | ||||
|             .map(orderedTagId => { | ||||
|  | @ -636,29 +611,6 @@ export default class RoomList extends React.PureComponent<IProps, IState> { | |||
|     } | ||||
| 
 | ||||
|     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(); | ||||
|         return ( | ||||
|             <RovingTabIndexProvider handleHomeEnd handleUpDown onKeyDown={this.props.onKeyDown}> | ||||
|  | @ -673,7 +625,6 @@ export default class RoomList extends React.PureComponent<IProps, IState> { | |||
|                         ref={this.treeRef} | ||||
|                     > | ||||
|                         { sublists } | ||||
|                         { explorePrompt } | ||||
|                     </div> | ||||
|                 ) } | ||||
|             </RovingTabIndexProvider> | ||||
|  |  | |||
|  | @ -14,35 +14,22 @@ See the License for the specific language governing permissions and | |||
| 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 { 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 { useFeatureEnabled } from "../../../hooks/useSettings"; | ||||
| import SpaceStore from "../../../stores/spaces/SpaceStore"; | ||||
| import { ChevronFace, ContextMenuTooltipButton, useContextMenu } from "../../structures/ContextMenu"; | ||||
| import SpaceContextMenu from "../context_menus/SpaceContextMenu"; | ||||
| 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 { _t } from "../../../languageHandler"; | ||||
| import PosthogTrackers from "../../../PosthogTrackers"; | ||||
| import { UIComponent } from "../../../settings/UIFeature"; | ||||
| import { | ||||
|     getMetaSpaceName, | ||||
|     MetaSpace, | ||||
|  | @ -50,13 +37,24 @@ import { | |||
|     UPDATE_HOME_BEHAVIOUR, | ||||
|     UPDATE_SELECTED_SPACE, | ||||
| } 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 PosthogTrackers from "../../../PosthogTrackers"; | ||||
| import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload"; | ||||
| import { useWebSearchMetrics } from "../dialogs/spotlight/SpotlightDialog"; | ||||
| import { shouldShowComponent } from "../../../customisations/helpers/UIComponents"; | ||||
| import { UIComponent } from "../../../settings/UIFeature"; | ||||
| import IconizedContextMenu, { | ||||
|     IconizedContextMenuOption, | ||||
|     IconizedContextMenuOptionList, | ||||
| } from "../context_menus/IconizedContextMenu"; | ||||
| 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) => { | ||||
|     // 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 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; | ||||
| 
 | ||||
|     useEffect(() => { | ||||
|  | @ -149,22 +138,13 @@ const RoomListHeader = ({ onVisibilityChange }: IProps) => { | |||
|         } | ||||
|     }, [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); | ||||
| 
 | ||||
|     useEffect(() => { | ||||
|         if (onVisibilityChange) { | ||||
|             onVisibilityChange(); | ||||
|         } | ||||
|     }, [count, onVisibilityChange]); | ||||
| 
 | ||||
|     if (typeof count === "number") { | ||||
|         return <div className="mx_LeftPanel_roomListFilterCount"> | ||||
|             { _t("%(count)s results", { count }) } | ||||
|         </div>; | ||||
|     } | ||||
|     }, [onVisibilityChange]); | ||||
| 
 | ||||
|     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. | ||||
| */ | ||||
| 
 | ||||
| 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 { Dispatcher } from "flux"; | ||||
| import { Room } from "matrix-js-sdk/src/models/room"; | ||||
| import { Enable, Resizable } from "re-resizable"; | ||||
| 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 { 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 AccessibleButton from "../../views/elements/AccessibleButton"; | ||||
| import RoomTile from "./RoomTile"; | ||||
| import { ListNotificationState } from "../../../stores/notifications/ListNotificationState"; | ||||
| import { RoomNotificationStateStore } from "../../../stores/notifications/RoomNotificationStateStore"; | ||||
| import { ListAlgorithm, SortAlgorithm } from "../../../stores/room-list/algorithms/models"; | ||||
| 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, { | ||||
|     ChevronFace, | ||||
|     ContextMenuTooltipButton, | ||||
|     StyledMenuItemCheckbox, | ||||
|     StyledMenuItemRadio, | ||||
| } from "../../structures/ContextMenu"; | ||||
| import RoomListStore, { LISTS_UPDATE_EVENT } from "../../../stores/room-list/RoomListStore"; | ||||
| 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 AccessibleButton from "../../views/elements/AccessibleButton"; | ||||
| 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 { ListNotificationState } from "../../../stores/notifications/ListNotificationState"; | ||||
| import { getKeyBindingsManager } from "../../../KeyBindingsManager"; | ||||
| import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts"; | ||||
| import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload"; | ||||
| import NotificationBadge from "./NotificationBadge"; | ||||
| import RoomTile from "./RoomTile"; | ||||
| 
 | ||||
| const SHOW_N_BUTTON_HEIGHT = 28; // 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
 | ||||
|     height: number; | ||||
|     rooms: Room[]; | ||||
|     filteredExtraTiles?: ReactComponentElement<typeof ExtraTile>[]; | ||||
| } | ||||
| 
 | ||||
| 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 layout: ListLayout; | ||||
|     private heightAtStart: number; | ||||
|     private isBeingFiltered: boolean; | ||||
|     private notificationState: ListNotificationState; | ||||
| 
 | ||||
|     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.heightAtStart = 0; | ||||
|         this.isBeingFiltered = !!RoomListStore.instance.getFirstNameFilterCondition(); | ||||
|         this.notificationState = RoomNotificationStateStore.instance.getListState(this.props.tagId); | ||||
|         this.state = { | ||||
|             contextMenuPosition: null, | ||||
|             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.
 | ||||
|             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 { | ||||
|         if (this.state.filteredExtraTiles) { | ||||
|             return this.state.filteredExtraTiles; | ||||
|         } | ||||
|         if (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>) { | ||||
|         const prevExtraTiles = prevState.filteredExtraTiles || prevProps.extraTiles; | ||||
|         const prevExtraTiles = prevProps.extraTiles; | ||||
|         // 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
 | ||||
|         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
 | ||||
|         // time so we don't have to consider them as part of the visible room optimization.
 | ||||
|         const prevExtraTiles = this.props.extraTiles || []; | ||||
|         const nextExtraTiles = (nextState.filteredExtraTiles || nextProps.extraTiles) || []; | ||||
|         const nextExtraTiles = nextProps.extraTiles || []; | ||||
|         if (prevExtraTiles.length > 0 || nextExtraTiles.length > 0) { | ||||
|             return true; | ||||
|         } | ||||
|  | @ -260,32 +253,12 @@ export default class RoomSublist extends React.Component<IProps, IState> { | |||
|     private onListsUpdated = () => { | ||||
|         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 newRooms = arrayFastClone(RoomListStore.instance.orderedLists[this.props.tagId] || []); | ||||
|         if (arrayHasOrderChange(currentRooms, 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) { | ||||
|             this.setState(stateUpdates); | ||||
|         } | ||||
|  | @ -418,7 +391,7 @@ export default class RoomSublist extends React.Component<IProps, IState> { | |||
|             room = this.state.rooms && this.state.rooms[0]; | ||||
|         } else { | ||||
|             // 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); | ||||
|                 return notifState.count > 0 && notifState.color === this.notificationState.color; | ||||
|             }); | ||||
|  |  | |||
|  | @ -1791,11 +1791,6 @@ | |||
|     "Historical": "Historical", | ||||
|     "Suggested Rooms": "Suggested Rooms", | ||||
|     "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", | ||||
|     "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", | ||||
|  |  | |||
|  | @ -26,14 +26,13 @@ import { IListOrderingMap, ITagMap, ITagSortingMap, ListAlgorithm, SortAlgorithm | |||
| import { ActionPayload } from "../../dispatcher/payloads"; | ||||
| import defaultDispatcher from "../../dispatcher/dispatcher"; | ||||
| 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 { Algorithm, LIST_UPDATED_EVENT } from "./algorithms/Algorithm"; | ||||
| import { EffectiveMembership, getEffectiveMembership } from "../../utils/membership"; | ||||
| import RoomListLayoutStore from "./RoomListLayoutStore"; | ||||
| import { MarkedExecution } from "../../utils/MarkedExecution"; | ||||
| import { AsyncStoreWithClient } from "../AsyncStoreWithClient"; | ||||
| import { NameFilterCondition } from "./filters/NameFilterCondition"; | ||||
| import { RoomNotificationStateStore } from "../notifications/RoomNotificationStateStore"; | ||||
| import { VisibilityProvider } from "./filters/VisibilityProvider"; | ||||
| import { SpaceWatcher } from "./SpaceWatcher"; | ||||
|  | @ -58,7 +57,6 @@ export class RoomListStoreClass extends AsyncStoreWithClient<IState> { | |||
| 
 | ||||
|     private initialListsGenerated = false; | ||||
|     private algorithm = new Algorithm(); | ||||
|     private filterConditions: IFilterCondition[] = []; | ||||
|     private prefilterConditions: IFilterCondition[] = []; | ||||
|     private updateFn = new MarkedExecution(() => { | ||||
|         for (const tagId of Object.keys(this.orderedLists)) { | ||||
|  | @ -78,11 +76,6 @@ export class RoomListStoreClass extends AsyncStoreWithClient<IState> { | |||
|         new SpaceWatcher(this); | ||||
|     } | ||||
| 
 | ||||
|     public get unfilteredLists(): ITagMap { | ||||
|         if (!this.algorithm) return {}; // No tags yet.
 | ||||
|         return this.algorithm.getUnfilteredRooms(); | ||||
|     } | ||||
| 
 | ||||
|     public get orderedLists(): ITagMap { | ||||
|         if (!this.algorithm) return {}; // No tags yet.
 | ||||
|         return this.algorithm.getOrderedRooms(); | ||||
|  | @ -91,7 +84,6 @@ export class RoomListStoreClass extends AsyncStoreWithClient<IState> { | |||
|     // Intended for test usage
 | ||||
|     public async resetStore() { | ||||
|         await this.reset(); | ||||
|         this.filterConditions = []; | ||||
|         this.prefilterConditions = []; | ||||
|         this.initialListsGenerated = false; | ||||
| 
 | ||||
|  | @ -502,9 +494,7 @@ export class RoomListStoreClass extends AsyncStoreWithClient<IState> { | |||
| 
 | ||||
|         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
 | ||||
|         // for the search all spaces feature
 | ||||
|         if (this.prefilterConditions.length > 0 && !this.filterConditions.length) { | ||||
|         if (this.prefilterConditions.length > 0) { | ||||
|             rooms = rooms.filter(r => { | ||||
|                 for (const filter of this.prefilterConditions) { | ||||
|                     if (!filter.isVisible(r)) { | ||||
|  | @ -556,20 +546,9 @@ export class RoomListStoreClass extends AsyncStoreWithClient<IState> { | |||
|      */ | ||||
|     public async addFilter(filter: IFilterCondition): Promise<void> { | ||||
|         let promise = Promise.resolve(); | ||||
|         if (filter.kind === FilterKind.Prefilter) { | ||||
|             filter.on(FILTER_CHANGED, this.onPrefilterUpdated); | ||||
|             this.prefilterConditions.push(filter); | ||||
|             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); | ||||
|             } | ||||
|         } | ||||
|         filter.on(FILTER_CHANGED, this.onPrefilterUpdated); | ||||
|         this.prefilterConditions.push(filter); | ||||
|         promise = this.recalculatePrefiltering(); | ||||
|         promise.then(() => this.updateFn.trigger()); | ||||
|     } | ||||
| 
 | ||||
|  | @ -582,20 +561,8 @@ export class RoomListStoreClass extends AsyncStoreWithClient<IState> { | |||
|      */ | ||||
|     public removeFilter(filter: IFilterCondition): void { | ||||
|         let promise = Promise.resolve(); | ||||
|         let idx = this.filterConditions.indexOf(filter); | ||||
|         let removed = false; | ||||
|         if (idx >= 0) { | ||||
|             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); | ||||
|         const idx = this.prefilterConditions.indexOf(filter); | ||||
|         if (idx >= 0) { | ||||
|             filter.off(FILTER_CHANGED, this.onPrefilterUpdated); | ||||
|             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 | ||||
|      * should never be empty, and will contain DefaultTagID.Untagged if | ||||
|  |  | |||
|  | @ -30,7 +30,6 @@ import { | |||
|     ListAlgorithm, | ||||
|     SortAlgorithm, | ||||
| } from "./models"; | ||||
| import { FILTER_CHANGED, IFilterCondition } from "../filters/IFilterCondition"; | ||||
| import { EffectiveMembership, getEffectiveMembership, splitRoomsByMembership } from "../../../utils/membership"; | ||||
| import { OrderingAlgorithm } from "./list-ordering/OrderingAlgorithm"; | ||||
| import { getListAlgorithmInstance } from "./list-ordering"; | ||||
|  | @ -67,7 +66,6 @@ interface IStickyRoom { | |||
| export class Algorithm extends EventEmitter { | ||||
|     private _cachedRooms: ITagMap = {}; | ||||
|     private _cachedStickyRooms: ITagMap = {}; // a clone of the _cachedRooms, with the sticky room
 | ||||
|     private filteredRooms: ITagMap = {}; | ||||
|     private _stickyRoom: IStickyRoom = null; | ||||
|     private _lastStickyRoom: IStickyRoom = null; // only not-null when changing the sticky room
 | ||||
|     private sortAlgorithms: ITagSortingMap; | ||||
|  | @ -77,8 +75,6 @@ export class Algorithm extends EventEmitter { | |||
|     private roomIdsToTags: { | ||||
|         [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. | ||||
|  | @ -107,13 +103,8 @@ export class Algorithm extends EventEmitter { | |||
|         return !!this.sortAlgorithms; | ||||
|     } | ||||
| 
 | ||||
|     protected get hasFilters(): boolean { | ||||
|         return this.allowedByFilter.size > 0; | ||||
|     } | ||||
| 
 | ||||
|     protected set cachedRooms(val: ITagMap) { | ||||
|         this._cachedRooms = val; | ||||
|         this.recalculateFilteredRooms(); | ||||
|         this.recalculateStickyRoom(); | ||||
|         this.recalculateVideoRoom(); | ||||
|     } | ||||
|  | @ -151,7 +142,6 @@ export class Algorithm extends EventEmitter { | |||
|         const algorithm: OrderingAlgorithm = this.algorithms[tagId]; | ||||
|         algorithm.setSortAlgorithm(sort); | ||||
|         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.recalculateVideoRoom(tagId); | ||||
|     } | ||||
|  | @ -171,40 +161,10 @@ export class Algorithm extends EventEmitter { | |||
| 
 | ||||
|         algorithm.setRooms(this._cachedRooms[tagId]); | ||||
|         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.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) { | ||||
|         this.doUpdateStickyRoom(val); | ||||
|         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
 | ||||
|         // 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.recalculateFilteredRoomsForTag(tag); | ||||
|         if (lastStickyRoom && lastStickyRoom.tag !== tag) this.recalculateFilteredRoomsForTag(lastStickyRoom.tag); | ||||
|         this.recalculateStickyRoom(); | ||||
|         this.recalculateVideoRoom(tag); | ||||
|         if (lastStickyRoom && lastStickyRoom.tag !== tag) this.recalculateVideoRoom(lastStickyRoom.tag); | ||||
|  | @ -334,7 +292,6 @@ export class Algorithm extends EventEmitter { | |||
|      */ | ||||
|     public updateVideoRoom = () => { | ||||
|         // In case we're unsticking a video room, sort it back into natural order
 | ||||
|         this.recalculateFilteredRooms(); | ||||
|         this.recalculateStickyRoom(); | ||||
| 
 | ||||
|         this.recalculateVideoRoom(); | ||||
|  | @ -345,63 +302,6 @@ export class Algorithm extends EventEmitter { | |||
|         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() { | ||||
|         this._cachedStickyRooms = {}; | ||||
|         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, | ||||
|      * for each tag. May be empty, but never null/undefined. | ||||
|      */ | ||||
|     public getOrderedRooms(): ITagMap { | ||||
|         if (!this.hasFilters) { | ||||
|             return this._cachedStickyRooms || this.cachedRooms; | ||||
|         } | ||||
|         return this.filteredRooms; | ||||
|     } | ||||
| 
 | ||||
|     public getUnfilteredRooms(): ITagMap { | ||||
|         return this._cachedStickyRooms || this.cachedRooms; | ||||
|     } | ||||
| 
 | ||||
|  | @ -543,10 +436,7 @@ export class Algorithm extends EventEmitter { | |||
|      * for each tag. May be empty, but never null/undefined. | ||||
|      */ | ||||
|     private getOrderedRoomsWithoutSticky(): ITagMap { | ||||
|         if (!this.hasFilters) { | ||||
|             return this.cachedRooms; | ||||
|         } | ||||
|         return this.filteredRooms; | ||||
|         return this.cachedRooms; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | @ -775,7 +665,6 @@ export class Algorithm extends EventEmitter { | |||
|                     if (!algorithm) throw new Error(`No algorithm for ${rmTag}`); | ||||
|                     algorithm.handleRoomUpdate(room, RoomUpdateCause.RoomRemoved); | ||||
|                     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.recalculateVideoRoom(rmTag); | ||||
|                 } | ||||
|  | @ -852,7 +741,6 @@ export class Algorithm extends EventEmitter { | |||
|             this._cachedRooms[tag] = algorithm.orderedRooms; | ||||
| 
 | ||||
|             // 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.recalculateVideoRoom(tag); | ||||
|             changed = true; | ||||
|  |  | |||
|  | @ -19,21 +19,6 @@ import { EventEmitter } from "events"; | |||
| 
 | ||||
| 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 | ||||
|  * should be shown or not. | ||||
|  | @ -47,11 +32,6 @@ export enum FilterKind { | |||
|  * as a change in the user's input), this emits FILTER_CHANGED. | ||||
|  */ | ||||
| export interface IFilterCondition extends EventEmitter { | ||||
|     /** | ||||
|      * The kind of filter this presents. | ||||
|      */ | ||||
|     kind: FilterKind; | ||||
| 
 | ||||
|     /** | ||||
|      * Determines if a given room should be visible under this | ||||
|      * 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 { 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 SpaceStore from "../../spaces/SpaceStore"; | ||||
| import { isMetaSpace, MetaSpace, SpaceKey } from "../../spaces"; | ||||
|  | @ -36,10 +36,6 @@ export class SpaceFilterCondition extends EventEmitter implements IFilterConditi | |||
|     private showPeopleInSpace = true; | ||||
|     private space: SpaceKey = MetaSpace.Home; | ||||
| 
 | ||||
|     public get kind(): FilterKind { | ||||
|         return FilterKind.Prefilter; | ||||
|     } | ||||
| 
 | ||||
|     public isVisible(room: Room): boolean { | ||||
|         return SpaceStore.instance.isRoomInSpace(this.space, room.roomId); | ||||
|     } | ||||
|  |  | |||
|  | @ -187,7 +187,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> { | |||
|                 metricsTrigger: "WebSpacePanelNotificationBadge", | ||||
|             }); | ||||
|         } else { | ||||
|             const lists = RoomListStore.instance.unfilteredLists; | ||||
|             const lists = RoomListStore.instance.orderedLists; | ||||
|             for (let i = 0; i < TAG_ORDER.length; i++) { | ||||
|                 const t = TAG_ORDER[i]; | ||||
|                 const listRooms = lists[t]; | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Janne Mareike Koschinski
						Janne Mareike Koschinski