mirror of https://github.com/vector-im/riot-web
Merge pull request #4862 from matrix-org/joriks/room-list-breadcrumbs
Implement breadcrumb notifications and scrollingpull/21833/head
commit
e98f6ca656
|
@ -49,6 +49,7 @@
|
||||||
@import "./views/auth/_ServerTypeSelector.scss";
|
@import "./views/auth/_ServerTypeSelector.scss";
|
||||||
@import "./views/auth/_Welcome.scss";
|
@import "./views/auth/_Welcome.scss";
|
||||||
@import "./views/avatars/_BaseAvatar.scss";
|
@import "./views/avatars/_BaseAvatar.scss";
|
||||||
|
@import "./views/avatars/_DecoratedRoomAvatar.scss";
|
||||||
@import "./views/avatars/_MemberStatusMessageAvatar.scss";
|
@import "./views/avatars/_MemberStatusMessageAvatar.scss";
|
||||||
@import "./views/context_menus/_MessageContextMenu.scss";
|
@import "./views/context_menus/_MessageContextMenu.scss";
|
||||||
@import "./views/context_menus/_RoomTileContextMenu.scss";
|
@import "./views/context_menus/_RoomTileContextMenu.scss";
|
||||||
|
|
|
@ -70,7 +70,8 @@ $tagPanelWidth: 70px; // only applies in this file, used for calculations
|
||||||
|
|
||||||
.mx_LeftPanel2_breadcrumbsContainer {
|
.mx_LeftPanel2_breadcrumbsContainer {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: hidden;
|
overflow-y: hidden;
|
||||||
|
overflow-x: scroll;
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.mx_DecoratedRoomAvatar {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.mx_RoomTileIcon {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_NotificationBadge {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 18px;
|
||||||
|
width: 18px;
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,15 +29,8 @@ limitations under the License.
|
||||||
border-radius: 32px;
|
border-radius: 32px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_RoomTile2_avatarContainer {
|
.mx_DecoratedRoomAvatar {
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.mx_RoomTileIcon {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_RoomTile2_nameContainer {
|
.mx_RoomTile2_nameContainer {
|
||||||
|
@ -155,16 +148,9 @@ limitations under the License.
|
||||||
align-items: center;
|
align-items: center;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
.mx_RoomTile2_avatarContainer {
|
.mx_DecoratedRoomAvatar {
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_RoomTile2_badgeContainer {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
height: 18px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ import { BreadcrumbsStore } from "../../stores/BreadcrumbsStore";
|
||||||
import { UPDATE_EVENT } from "../../stores/AsyncStore";
|
import { UPDATE_EVENT } from "../../stores/AsyncStore";
|
||||||
import ResizeNotifier from "../../utils/ResizeNotifier";
|
import ResizeNotifier from "../../utils/ResizeNotifier";
|
||||||
import SettingsStore from "../../settings/SettingsStore";
|
import SettingsStore from "../../settings/SettingsStore";
|
||||||
|
import RoomListStore, { RoomListStore2, LISTS_UPDATE_EVENT } from "../../stores/room-list/RoomListStore2";
|
||||||
|
|
||||||
// TODO: Remove banner on launch: https://github.com/vector-im/riot-web/issues/14231
|
// TODO: Remove banner on launch: https://github.com/vector-im/riot-web/issues/14231
|
||||||
// TODO: Rename on launch: https://github.com/vector-im/riot-web/issues/14231
|
// TODO: Rename on launch: https://github.com/vector-im/riot-web/issues/14231
|
||||||
|
@ -69,6 +70,7 @@ export default class LeftPanel2 extends React.Component<IProps, IState> {
|
||||||
};
|
};
|
||||||
|
|
||||||
BreadcrumbsStore.instance.on(UPDATE_EVENT, this.onBreadcrumbsUpdate);
|
BreadcrumbsStore.instance.on(UPDATE_EVENT, this.onBreadcrumbsUpdate);
|
||||||
|
RoomListStore.instance.on(LISTS_UPDATE_EVENT, this.onBreadcrumbsUpdate);
|
||||||
this.tagPanelWatcherRef = SettingsStore.watchSetting("TagPanel.enableTagPanel", null, () => {
|
this.tagPanelWatcherRef = SettingsStore.watchSetting("TagPanel.enableTagPanel", null, () => {
|
||||||
this.setState({showTagPanel: SettingsStore.getValue("TagPanel.enableTagPanel")});
|
this.setState({showTagPanel: SettingsStore.getValue("TagPanel.enableTagPanel")});
|
||||||
});
|
});
|
||||||
|
@ -81,6 +83,7 @@ export default class LeftPanel2 extends React.Component<IProps, IState> {
|
||||||
public componentWillUnmount() {
|
public componentWillUnmount() {
|
||||||
SettingsStore.unwatchSetting(this.tagPanelWatcherRef);
|
SettingsStore.unwatchSetting(this.tagPanelWatcherRef);
|
||||||
BreadcrumbsStore.instance.off(UPDATE_EVENT, this.onBreadcrumbsUpdate);
|
BreadcrumbsStore.instance.off(UPDATE_EVENT, this.onBreadcrumbsUpdate);
|
||||||
|
RoomListStore.instance.off(LISTS_UPDATE_EVENT, this.onBreadcrumbsUpdate);
|
||||||
this.props.resizeNotifier.off("middlePanelResizedNoisy", this.onResize);
|
this.props.resizeNotifier.off("middlePanelResizedNoisy", this.onResize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,7 +154,7 @@ export default class LeftPanel2 extends React.Component<IProps, IState> {
|
||||||
let breadcrumbs;
|
let breadcrumbs;
|
||||||
if (this.state.showBreadcrumbs) {
|
if (this.state.showBreadcrumbs) {
|
||||||
breadcrumbs = (
|
breadcrumbs = (
|
||||||
<div className="mx_LeftPanel2_headerRow mx_LeftPanel2_breadcrumbsContainer">
|
<div className="mx_LeftPanel2_headerRow mx_LeftPanel2_breadcrumbsContainer mx_AutoHideScrollbar">
|
||||||
{this.props.isMinimized ? null : <RoomBreadcrumbs2 />}
|
{this.props.isMinimized ? null : <RoomBreadcrumbs2 />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 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 React from 'react';
|
||||||
|
import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
|
|
||||||
|
import { TagID } from '../../../stores/room-list/models';
|
||||||
|
import RoomAvatar from "./RoomAvatar";
|
||||||
|
import RoomTileIcon from "../rooms/RoomTileIcon";
|
||||||
|
import NotificationBadge, { INotificationState, TagSpecificNotificationState } from '../rooms/NotificationBadge';
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
room: Room;
|
||||||
|
avatarSize: number;
|
||||||
|
tag: TagID;
|
||||||
|
displayBadge?: boolean;
|
||||||
|
forceCount?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IState {
|
||||||
|
notificationState?: INotificationState;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class DecoratedRoomAvatar extends React.PureComponent<IProps, IState> {
|
||||||
|
|
||||||
|
constructor(props: IProps) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
notificationState: new TagSpecificNotificationState(this.props.room, this.props.tag),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public render(): React.ReactNode {
|
||||||
|
let badge: React.ReactNode;
|
||||||
|
if (this.props.displayBadge) {
|
||||||
|
badge = <NotificationBadge
|
||||||
|
notification={this.state.notificationState}
|
||||||
|
forceCount={this.props.forceCount}
|
||||||
|
roomId={this.props.room.roomId}
|
||||||
|
/>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div className="mx_DecoratedRoomAvatar">
|
||||||
|
<RoomAvatar room={this.props.room} width={this.props.avatarSize} height={this.props.avatarSize} />
|
||||||
|
<RoomTileIcon room={this.props.room} tag={this.props.tag} />
|
||||||
|
{badge}
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,13 +17,15 @@ limitations under the License.
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { BreadcrumbsStore } from "../../../stores/BreadcrumbsStore";
|
import { BreadcrumbsStore } from "../../../stores/BreadcrumbsStore";
|
||||||
import AccessibleButton from "../elements/AccessibleButton";
|
import AccessibleButton from "../elements/AccessibleButton";
|
||||||
import RoomAvatar from "../avatars/RoomAvatar";
|
import DecoratedRoomAvatar from "../avatars/DecoratedRoomAvatar";
|
||||||
import { _t } from "../../../languageHandler";
|
import { _t } from "../../../languageHandler";
|
||||||
import { Room } from "matrix-js-sdk/src/models/room";
|
import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
import defaultDispatcher from "../../../dispatcher/dispatcher";
|
import defaultDispatcher from "../../../dispatcher/dispatcher";
|
||||||
import Analytics from "../../../Analytics";
|
import Analytics from "../../../Analytics";
|
||||||
import { UPDATE_EVENT } from "../../../stores/AsyncStore";
|
import { UPDATE_EVENT } from "../../../stores/AsyncStore";
|
||||||
import { CSSTransition } from "react-transition-group";
|
import { CSSTransition } from "react-transition-group";
|
||||||
|
import RoomListStore from "../../../stores/room-list/RoomListStore2";
|
||||||
|
import { DefaultTagID } from "../../../stores/room-list/models";
|
||||||
|
|
||||||
// TODO: Remove banner on launch: https://github.com/vector-im/riot-web/issues/14231
|
// TODO: Remove banner on launch: https://github.com/vector-im/riot-web/issues/14231
|
||||||
// TODO: Rename on launch: https://github.com/vector-im/riot-web/issues/14231
|
// TODO: Rename on launch: https://github.com/vector-im/riot-web/issues/14231
|
||||||
|
@ -93,6 +95,8 @@ export default class RoomBreadcrumbs2 extends React.PureComponent<IProps, IState
|
||||||
// TODO: Scrolling: https://github.com/vector-im/riot-web/issues/14040
|
// TODO: Scrolling: https://github.com/vector-im/riot-web/issues/14040
|
||||||
// TODO: Tooltips: https://github.com/vector-im/riot-web/issues/14040
|
// TODO: Tooltips: https://github.com/vector-im/riot-web/issues/14040
|
||||||
const tiles = BreadcrumbsStore.instance.rooms.map((r, i) => {
|
const tiles = BreadcrumbsStore.instance.rooms.map((r, i) => {
|
||||||
|
const roomTags = RoomListStore.instance.getTagsForRoom(r);
|
||||||
|
const roomTag = roomTags.includes(DefaultTagID.DM) ? DefaultTagID.DM : roomTags[0];
|
||||||
return (
|
return (
|
||||||
<AccessibleButton
|
<AccessibleButton
|
||||||
className="mx_RoomBreadcrumbs2_crumb"
|
className="mx_RoomBreadcrumbs2_crumb"
|
||||||
|
@ -100,7 +104,13 @@ export default class RoomBreadcrumbs2 extends React.PureComponent<IProps, IState
|
||||||
onClick={() => this.viewRoom(r, i)}
|
onClick={() => this.viewRoom(r, i)}
|
||||||
aria-label={_t("Room %(name)s", {name: r.name})}
|
aria-label={_t("Room %(name)s", {name: r.name})}
|
||||||
>
|
>
|
||||||
<RoomAvatar room={r} width={32} height={32}/>
|
<DecoratedRoomAvatar
|
||||||
|
room={r}
|
||||||
|
avatarSize={32}
|
||||||
|
tag={roomTag}
|
||||||
|
displayBadge={true}
|
||||||
|
forceCount={true}
|
||||||
|
/>
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -22,7 +22,6 @@ import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { RovingTabIndexWrapper } from "../../../accessibility/RovingTabIndex";
|
import { RovingTabIndexWrapper } from "../../../accessibility/RovingTabIndex";
|
||||||
import AccessibleButton, { ButtonEvent } from "../../views/elements/AccessibleButton";
|
import AccessibleButton, { ButtonEvent } from "../../views/elements/AccessibleButton";
|
||||||
import RoomAvatar from "../../views/avatars/RoomAvatar";
|
|
||||||
import dis from '../../../dispatcher/dispatcher';
|
import dis from '../../../dispatcher/dispatcher';
|
||||||
import { Key } from "../../../Keyboard";
|
import { Key } from "../../../Keyboard";
|
||||||
import ActiveRoomObserver from "../../../ActiveRoomObserver";
|
import ActiveRoomObserver from "../../../ActiveRoomObserver";
|
||||||
|
@ -35,6 +34,7 @@ import { _t } from "../../../languageHandler";
|
||||||
import { ContextMenu, ContextMenuButton, MenuItemRadio } from "../../structures/ContextMenu";
|
import { ContextMenu, ContextMenuButton, MenuItemRadio } from "../../structures/ContextMenu";
|
||||||
import { DefaultTagID, TagID } from "../../../stores/room-list/models";
|
import { DefaultTagID, TagID } from "../../../stores/room-list/models";
|
||||||
import { MessagePreviewStore } from "../../../stores/room-list/MessagePreviewStore";
|
import { MessagePreviewStore } from "../../../stores/room-list/MessagePreviewStore";
|
||||||
|
import DecoratedRoomAvatar from "../avatars/DecoratedRoomAvatar";
|
||||||
import RoomTileIcon from "./RoomTileIcon";
|
import RoomTileIcon from "./RoomTileIcon";
|
||||||
import { getRoomNotifsState, ALL_MESSAGES, ALL_MESSAGES_LOUD, MENTIONS_ONLY, MUTE } from "../../../RoomNotifs";
|
import { getRoomNotifsState, ALL_MESSAGES, ALL_MESSAGES_LOUD, MENTIONS_ONLY, MUTE } from "../../../RoomNotifs";
|
||||||
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||||
|
@ -361,13 +361,21 @@ export default class RoomTile2 extends React.Component<IProps, IState> {
|
||||||
'mx_RoomTile2_minimized': this.props.isMinimized,
|
'mx_RoomTile2_minimized': this.props.isMinimized,
|
||||||
});
|
});
|
||||||
|
|
||||||
const badge = (
|
const roomAvatar = <DecoratedRoomAvatar
|
||||||
<NotificationBadge
|
room={this.props.room}
|
||||||
|
avatarSize={32}
|
||||||
|
tag={this.props.tag}
|
||||||
|
displayBadge={this.props.isMinimized}
|
||||||
|
/>;
|
||||||
|
|
||||||
|
let badge: React.ReactNode;
|
||||||
|
if (!this.props.isMinimized) {
|
||||||
|
badge = <NotificationBadge
|
||||||
notification={this.state.notificationState}
|
notification={this.state.notificationState}
|
||||||
forceCount={false}
|
forceCount={false}
|
||||||
roomId={this.props.room.roomId}
|
roomId={this.props.room.roomId}
|
||||||
/>
|
/>;
|
||||||
);
|
}
|
||||||
|
|
||||||
// TODO: the original RoomTile uses state for the room name. Do we need to?
|
// TODO: the original RoomTile uses state for the room name. Do we need to?
|
||||||
let name = this.props.room.name;
|
let name = this.props.room.name;
|
||||||
|
@ -405,7 +413,6 @@ export default class RoomTile2 extends React.Component<IProps, IState> {
|
||||||
);
|
);
|
||||||
if (this.props.isMinimized) nameContainer = null;
|
if (this.props.isMinimized) nameContainer = null;
|
||||||
|
|
||||||
const avatarSize = 32;
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<RovingTabIndexWrapper>
|
<RovingTabIndexWrapper>
|
||||||
|
@ -421,10 +428,7 @@ export default class RoomTile2 extends React.Component<IProps, IState> {
|
||||||
role="treeitem"
|
role="treeitem"
|
||||||
onContextMenu={this.onContextMenu}
|
onContextMenu={this.onContextMenu}
|
||||||
>
|
>
|
||||||
<div className="mx_RoomTile2_avatarContainer">
|
{roomAvatar}
|
||||||
<RoomAvatar room={this.props.room} width={avatarSize} height={avatarSize} />
|
|
||||||
<RoomTileIcon room={this.props.room} tag={this.props.tag} />
|
|
||||||
</div>
|
|
||||||
{nameContainer}
|
{nameContainer}
|
||||||
<div className="mx_RoomTile2_badgeContainer">
|
<div className="mx_RoomTile2_badgeContainer">
|
||||||
{badge}
|
{badge}
|
||||||
|
|
|
@ -51,7 +51,7 @@ export class BreadcrumbsStore extends AsyncStoreWithClient<IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public get visible(): boolean {
|
public get visible(): boolean {
|
||||||
return this.state.enabled;
|
return this.state.enabled && this.matrixClient.getVisibleRooms().length >= 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async onAction(payload: ActionPayload) {
|
protected async onAction(payload: ActionPayload) {
|
||||||
|
|
|
@ -17,7 +17,7 @@ limitations under the License.
|
||||||
|
|
||||||
import { MatrixClient } from "matrix-js-sdk/src/client";
|
import { MatrixClient } from "matrix-js-sdk/src/client";
|
||||||
import SettingsStore from "../../settings/SettingsStore";
|
import SettingsStore from "../../settings/SettingsStore";
|
||||||
import { OrderedDefaultTagIDs, RoomUpdateCause, TagID } from "./models";
|
import { DefaultTagID, OrderedDefaultTagIDs, RoomUpdateCause, TagID } from "./models";
|
||||||
import TagOrderStore from "../TagOrderStore";
|
import TagOrderStore from "../TagOrderStore";
|
||||||
import { AsyncStore } from "../AsyncStore";
|
import { AsyncStore } from "../AsyncStore";
|
||||||
import { Room } from "matrix-js-sdk/src/models/room";
|
import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
|
@ -186,7 +186,8 @@ export class RoomListStore2 extends AsyncStore<ActionPayload> {
|
||||||
const room = this.matrixClient.getRoom(roomId);
|
const room = this.matrixClient.getRoom(roomId);
|
||||||
const tryUpdate = async (updatedRoom: Room) => {
|
const tryUpdate = async (updatedRoom: Room) => {
|
||||||
// TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
|
// TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
|
||||||
console.log(`[RoomListDebug] Live timeline event ${eventPayload.event.getId()} in ${updatedRoom.roomId}`);
|
console.log(`[RoomListDebug] Live timeline event ${eventPayload.event.getId()}` +
|
||||||
|
` in ${updatedRoom.roomId}`);
|
||||||
if (eventPayload.event.getType() === 'm.room.tombstone' && eventPayload.event.getStateKey() === '') {
|
if (eventPayload.event.getType() === 'm.room.tombstone' && eventPayload.event.getStateKey() === '') {
|
||||||
// TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
|
// TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
|
||||||
console.log(`[RoomListDebug] Got tombstone event - trying to remove now-dead room`);
|
console.log(`[RoomListDebug] Got tombstone event - trying to remove now-dead room`);
|
||||||
|
@ -427,6 +428,19 @@ export class RoomListStore2 extends AsyncStore<ActionPayload> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the tags for a room identified by the store. The returned set
|
||||||
|
* should never be empty, and will contain DefaultTagID.Untagged if
|
||||||
|
* the store is not aware of any tags.
|
||||||
|
* @param room The room to get the tags for.
|
||||||
|
* @returns The tags for the room.
|
||||||
|
*/
|
||||||
|
public getTagsForRoom(room: Room): TagID[] {
|
||||||
|
const algorithmTags = this.algorithm.getTagsForRoom(room);
|
||||||
|
if (!algorithmTags) return [DefaultTagID.Untagged];
|
||||||
|
return algorithmTags;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class RoomListStore {
|
export default class RoomListStore {
|
||||||
|
|
|
@ -524,7 +524,7 @@ export class Algorithm extends EventEmitter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private getTagsForRoom(room: Room): TagID[] {
|
public getTagsForRoom(room: Room): TagID[] {
|
||||||
// XXX: This duplicates a lot of logic from setKnownRooms above, but has a slightly
|
// XXX: This duplicates a lot of logic from setKnownRooms above, but has a slightly
|
||||||
// different use case and therefore different performance curve
|
// different use case and therefore different performance curve
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue