Experiment switching the Home Space out for an All rooms space

This commit is contained in:
Michael Telatynski 2021-05-04 18:06:43 +01:00
parent 48237949ad
commit a70be45b6e
8 changed files with 49 additions and 149 deletions

View file

@ -17,7 +17,6 @@ limitations under the License.
import * as React from "react"; import * as React from "react";
import { createRef } from "react"; import { createRef } from "react";
import classNames from "classnames"; import classNames from "classnames";
import { Room } from "matrix-js-sdk/src/models/room";
import defaultDispatcher from "../../dispatcher/dispatcher"; import defaultDispatcher from "../../dispatcher/dispatcher";
import { _t } from "../../languageHandler"; import { _t } from "../../languageHandler";
@ -27,8 +26,8 @@ import { Action } from "../../dispatcher/actions";
import RoomListStore from "../../stores/room-list/RoomListStore"; import RoomListStore from "../../stores/room-list/RoomListStore";
import { NameFilterCondition } from "../../stores/room-list/filters/NameFilterCondition"; import { NameFilterCondition } from "../../stores/room-list/filters/NameFilterCondition";
import { getKeyBindingsManager, RoomListAction } from "../../KeyBindingsManager"; import { getKeyBindingsManager, RoomListAction } from "../../KeyBindingsManager";
import {replaceableComponent} from "../../utils/replaceableComponent"; import { replaceableComponent } from "../../utils/replaceableComponent";
import SpaceStore, {UPDATE_SELECTED_SPACE, UPDATE_TOP_LEVEL_SPACES} from "../../stores/SpaceStore"; import SpaceStore, { UPDATE_SELECTED_SPACE } from "../../stores/SpaceStore";
interface IProps { interface IProps {
isMinimized: boolean; isMinimized: boolean;
@ -42,7 +41,6 @@ interface IProps {
interface IState { interface IState {
query: string; query: string;
focused: boolean; focused: boolean;
inSpaces: boolean;
} }
@replaceableComponent("structures.RoomSearch") @replaceableComponent("structures.RoomSearch")
@ -57,13 +55,11 @@ export default class RoomSearch extends React.PureComponent<IProps, IState> {
this.state = { this.state = {
query: "", query: "",
focused: false, focused: false,
inSpaces: false,
}; };
this.dispatcherRef = defaultDispatcher.register(this.onAction); this.dispatcherRef = defaultDispatcher.register(this.onAction);
// clear filter when changing spaces, in future we may wish to maintain a filter per-space // clear filter when changing spaces, in future we may wish to maintain a filter per-space
SpaceStore.instance.on(UPDATE_SELECTED_SPACE, this.clearInput); SpaceStore.instance.on(UPDATE_SELECTED_SPACE, this.clearInput);
SpaceStore.instance.on(UPDATE_TOP_LEVEL_SPACES, this.onSpaces);
} }
public componentDidUpdate(prevProps: Readonly<IProps>, prevState: Readonly<IState>): void { public componentDidUpdate(prevProps: Readonly<IProps>, prevState: Readonly<IState>): void {
@ -84,15 +80,8 @@ export default class RoomSearch extends React.PureComponent<IProps, IState> {
public componentWillUnmount() { public componentWillUnmount() {
defaultDispatcher.unregister(this.dispatcherRef); defaultDispatcher.unregister(this.dispatcherRef);
SpaceStore.instance.off(UPDATE_SELECTED_SPACE, this.clearInput); SpaceStore.instance.off(UPDATE_SELECTED_SPACE, this.clearInput);
SpaceStore.instance.off(UPDATE_TOP_LEVEL_SPACES, this.onSpaces);
} }
private onSpaces = (spaces: Room[]) => {
this.setState({
inSpaces: spaces.length > 0,
});
};
private onAction = (payload: ActionPayload) => { private onAction = (payload: ActionPayload) => {
if (payload.action === 'view_room' && payload.clear_search) { if (payload.action === 'view_room' && payload.clear_search) {
this.clearInput(); this.clearInput();
@ -164,11 +153,6 @@ export default class RoomSearch extends React.PureComponent<IProps, IState> {
'mx_RoomSearch_inputExpanded': this.state.query || this.state.focused, 'mx_RoomSearch_inputExpanded': this.state.query || this.state.focused,
}); });
let placeholder = _t("Filter");
if (this.state.inSpaces) {
placeholder = _t("Filter all spaces");
}
let icon = ( let icon = (
<div className='mx_RoomSearch_icon' /> <div className='mx_RoomSearch_icon' />
); );
@ -182,7 +166,7 @@ export default class RoomSearch extends React.PureComponent<IProps, IState> {
onBlur={this.onBlur} onBlur={this.onBlur}
onChange={this.onChange} onChange={this.onChange}
onKeyDown={this.onKeyDown} onKeyDown={this.onKeyDown}
placeholder={placeholder} placeholder={_t("Filter")}
autoComplete="off" autoComplete="off"
/> />
); );

View file

@ -19,7 +19,6 @@ import React, {useState} from "react";
import { _t } from "../../../languageHandler"; import { _t } from "../../../languageHandler";
import RoomListStore, { LISTS_UPDATE_EVENT } from "../../../stores/room-list/RoomListStore"; import RoomListStore, { LISTS_UPDATE_EVENT } from "../../../stores/room-list/RoomListStore";
import {useEventEmitter} from "../../../hooks/useEventEmitter"; import {useEventEmitter} from "../../../hooks/useEventEmitter";
import SpaceStore from "../../../stores/SpaceStore";
const RoomListNumResults: React.FC = () => { const RoomListNumResults: React.FC = () => {
const [count, setCount] = useState<number>(null); const [count, setCount] = useState<number>(null);
@ -35,10 +34,7 @@ const RoomListNumResults: React.FC = () => {
if (typeof count !== "number") return null; if (typeof count !== "number") return null;
return <div className="mx_LeftPanel_roomListFilterCount"> return <div className="mx_LeftPanel_roomListFilterCount">
{ SpaceStore.instance.spacePanelSpaces.length { _t("%(count)s results", { count }) }
? _t("%(count)s results in all spaces", { count })
: _t("%(count)s results", { count })
}
</div>; </div>;
}; };

View file

@ -26,13 +26,11 @@ import {SpaceItem} from "./SpaceTreeLevel";
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
import {useEventEmitter} from "../../../hooks/useEventEmitter"; import {useEventEmitter} from "../../../hooks/useEventEmitter";
import SpaceStore, { import SpaceStore, {
HOME_SPACE,
UPDATE_INVITED_SPACES, UPDATE_INVITED_SPACES,
UPDATE_SELECTED_SPACE, UPDATE_SELECTED_SPACE,
UPDATE_TOP_LEVEL_SPACES, UPDATE_TOP_LEVEL_SPACES,
} from "../../../stores/SpaceStore"; } from "../../../stores/SpaceStore";
import AutoHideScrollbar from "../../structures/AutoHideScrollbar"; import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
import {SpaceNotificationState} from "../../../stores/notifications/SpaceNotificationState";
import NotificationBadge from "../rooms/NotificationBadge"; import NotificationBadge from "../rooms/NotificationBadge";
import { import {
RovingAccessibleButton, RovingAccessibleButton,
@ -40,13 +38,15 @@ import {
RovingTabIndexProvider, RovingTabIndexProvider,
} from "../../../accessibility/RovingTabIndex"; } from "../../../accessibility/RovingTabIndex";
import {Key} from "../../../Keyboard"; import {Key} from "../../../Keyboard";
import {RoomNotificationStateStore} from "../../../stores/notifications/RoomNotificationStateStore";
import {NotificationState} from "../../../stores/notifications/NotificationState";
interface IButtonProps { interface IButtonProps {
space?: Room; space?: Room;
className?: string; className?: string;
selected?: boolean; selected?: boolean;
tooltip?: string; tooltip?: string;
notificationState?: SpaceNotificationState; notificationState?: NotificationState;
isNarrow?: boolean; isNarrow?: boolean;
onClick(): void; onClick(): void;
} }
@ -212,8 +212,8 @@ const SpacePanel = () => {
className="mx_SpaceButton_home" className="mx_SpaceButton_home"
onClick={() => SpaceStore.instance.setActiveSpace(null)} onClick={() => SpaceStore.instance.setActiveSpace(null)}
selected={!activeSpace} selected={!activeSpace}
tooltip={_t("Home")} tooltip={_t("All rooms")}
notificationState={SpaceStore.instance.getNotificationState(HOME_SPACE)} notificationState={RoomNotificationStateStore.instance.globalState}
isNarrow={isPanelCollapsed} isNarrow={isPanelCollapsed}
/> />
{ invites.map(s => <SpaceItem { invites.map(s => <SpaceItem

View file

@ -1011,7 +1011,7 @@
"Create": "Create", "Create": "Create",
"Expand space panel": "Expand space panel", "Expand space panel": "Expand space panel",
"Collapse space panel": "Collapse space panel", "Collapse space panel": "Collapse space panel",
"Home": "Home", "All rooms": "All rooms",
"Click to copy": "Click to copy", "Click to copy": "Click to copy",
"Copied!": "Copied!", "Copied!": "Copied!",
"Failed to copy": "Failed to copy", "Failed to copy": "Failed to copy",
@ -1552,8 +1552,6 @@
"Explore all public rooms": "Explore all public rooms", "Explore all public rooms": "Explore all public rooms",
"Quick actions": "Quick actions", "Quick actions": "Quick actions",
"Use the + to make a new room or explore existing ones below": "Use the + to make a new room or explore existing ones below", "Use the + to make a new room or explore existing ones below": "Use the + to make a new room or explore existing ones below",
"%(count)s results in all spaces|other": "%(count)s results in all spaces",
"%(count)s results in all spaces|one": "%(count)s result in all spaces",
"%(count)s results|other": "%(count)s results", "%(count)s results|other": "%(count)s results",
"%(count)s results|one": "%(count)s result", "%(count)s results|one": "%(count)s result",
"This room": "This room", "This room": "This room",
@ -2014,10 +2012,10 @@
"Continue with %(provider)s": "Continue with %(provider)s", "Continue with %(provider)s": "Continue with %(provider)s",
"Sign in with single sign-on": "Sign in with single sign-on", "Sign in with single sign-on": "Sign in with single sign-on",
"And %(count)s more...|other": "And %(count)s more...", "And %(count)s more...|other": "And %(count)s more...",
"Home": "Home",
"Enter a server name": "Enter a server name", "Enter a server name": "Enter a server name",
"Looks good": "Looks good", "Looks good": "Looks good",
"Can't find this server or its room list": "Can't find this server or its room list", "Can't find this server or its room list": "Can't find this server or its room list",
"All rooms": "All rooms",
"Your server": "Your server", "Your server": "Your server",
"Are you sure you want to remove <b>%(serverName)s</b>": "Are you sure you want to remove <b>%(serverName)s</b>", "Are you sure you want to remove <b>%(serverName)s</b>": "Are you sure you want to remove <b>%(serverName)s</b>",
"Remove server": "Remove server", "Remove server": "Remove server",
@ -2619,7 +2617,6 @@
"If you can't find the room you're looking for, ask for an invite or <a>Create a new room</a>.": "If you can't find the room you're looking for, ask for an invite or <a>Create a new room</a>.", "If you can't find the room you're looking for, ask for an invite or <a>Create a new room</a>.": "If you can't find the room you're looking for, ask for an invite or <a>Create a new room</a>.",
"Explore rooms in %(communityName)s": "Explore rooms in %(communityName)s", "Explore rooms in %(communityName)s": "Explore rooms in %(communityName)s",
"Filter": "Filter", "Filter": "Filter",
"Filter all spaces": "Filter all spaces",
"Clear filter": "Clear filter", "Clear filter": "Clear filter",
"Filter rooms and people": "Filter rooms and people", "Filter rooms and people": "Filter rooms and people",
"You can't send any messages until you review and agree to <consentLink>our terms and conditions</consentLink>.": "You can't send any messages until you review and agree to <consentLink>our terms and conditions</consentLink>.", "You can't send any messages until you review and agree to <consentLink>our terms and conditions</consentLink>.": "You can't send any messages until you review and agree to <consentLink>our terms and conditions</consentLink>.",

View file

@ -31,28 +31,23 @@ import {RoomNotificationStateStore} from "./notifications/RoomNotificationStateS
import {DefaultTagID} from "./room-list/models"; import {DefaultTagID} from "./room-list/models";
import {EnhancedMap, mapDiff} from "../utils/maps"; import {EnhancedMap, mapDiff} from "../utils/maps";
import {setHasDiff} from "../utils/sets"; import {setHasDiff} from "../utils/sets";
import {objectDiff} from "../utils/objects";
import {arrayHasDiff} from "../utils/arrays";
import {ISpaceSummaryEvent, ISpaceSummaryRoom} from "../components/structures/SpaceRoomDirectory"; import {ISpaceSummaryEvent, ISpaceSummaryRoom} from "../components/structures/SpaceRoomDirectory";
import RoomViewStore from "./RoomViewStore"; import RoomViewStore from "./RoomViewStore";
type SpaceKey = string | symbol;
interface IState {} interface IState {}
const ACTIVE_SPACE_LS_KEY = "mx_active_space"; const ACTIVE_SPACE_LS_KEY = "mx_active_space";
export const HOME_SPACE = Symbol("home-space");
export const SUGGESTED_ROOMS = Symbol("suggested-rooms"); export const SUGGESTED_ROOMS = Symbol("suggested-rooms");
export const UPDATE_TOP_LEVEL_SPACES = Symbol("top-level-spaces"); export const UPDATE_TOP_LEVEL_SPACES = Symbol("top-level-spaces");
export const UPDATE_INVITED_SPACES = Symbol("invited-spaces"); export const UPDATE_INVITED_SPACES = Symbol("invited-spaces");
export const UPDATE_SELECTED_SPACE = Symbol("selected-space"); export const UPDATE_SELECTED_SPACE = Symbol("selected-space");
// Space Room ID/HOME_SPACE will be emitted when a Space's children change // Space Room ID will be emitted when a Space's children change
const MAX_SUGGESTED_ROOMS = 20; const MAX_SUGGESTED_ROOMS = 20;
const getSpaceContextKey = (space?: Room) => `mx_space_context_${space?.roomId || "home_space"}`; const getSpaceContextKey = (space?: Room) => `mx_space_context_${space?.roomId || "ALL_ROOMS"}`;
const partitionSpacesAndRooms = (arr: Room[]): [Room[], Room[]] => { // [spaces, rooms] const partitionSpacesAndRooms = (arr: Room[]): [Room[], Room[]] => { // [spaces, rooms]
return arr.reduce((result, room: Room) => { return arr.reduce((result, room: Room) => {
@ -83,15 +78,13 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
// The spaces representing the roots of the various tree-like hierarchies // The spaces representing the roots of the various tree-like hierarchies
private rootSpaces: Room[] = []; private rootSpaces: Room[] = [];
// The list of rooms not present in any currently joined spaces
private orphanedRooms = new Set<string>();
// Map from room ID to set of spaces which list it as a child // Map from room ID to set of spaces which list it as a child
private parentMap = new EnhancedMap<string, Set<string>>(); private parentMap = new EnhancedMap<string, Set<string>>();
// Map from space key to SpaceNotificationState instance representing that space // Map from spaceId to SpaceNotificationState instance representing that space
private notificationStateMap = new Map<SpaceKey, SpaceNotificationState>(); private notificationStateMap = new Map<string, SpaceNotificationState>();
// Map from space key to Set of room IDs that should be shown as part of that space's filter // Map from space key to Set of room IDs that should be shown as part of that space's filter
private spaceFilteredRooms = new Map<string | symbol, Set<string>>(); private spaceFilteredRooms = new Map<string, Set<string>>();
// The space currently selected in the Space Panel - if null then `Home` is selected // The space currently selected in the Space Panel - if null then All Rooms is selected
private _activeSpace?: Room = null; private _activeSpace?: Room = null;
private _suggestedRooms: ISpaceSummaryRoom[] = []; private _suggestedRooms: ISpaceSummaryRoom[] = [];
private _invitedSpaces = new Set<Room>(); private _invitedSpaces = new Set<Room>();
@ -227,7 +220,10 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
} }
public getSpaceFilteredRoomIds = (space: Room | null): Set<string> => { public getSpaceFilteredRoomIds = (space: Room | null): Set<string> => {
return this.spaceFilteredRooms.get(space?.roomId || HOME_SPACE) || new Set(); if (!space) {
return new Set(this.matrixClient.getVisibleRooms().map(r => r.roomId));
}
return this.spaceFilteredRooms.get(space.roomId) || new Set();
}; };
private rebuild = throttle(() => { private rebuild = throttle(() => {
@ -258,7 +254,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
}); });
}); });
const [rootSpaces, orphanedRooms] = partitionSpacesAndRooms(Array.from(unseenChildren)); const [rootSpaces] = partitionSpacesAndRooms(Array.from(unseenChildren));
// somewhat algorithm to handle full-cycles // somewhat algorithm to handle full-cycles
const detachedNodes = new Set<Room>(spaces); const detachedNodes = new Set<Room>(spaces);
@ -299,7 +295,6 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
// rootSpaces.push(space); // rootSpaces.push(space);
// }); // });
this.orphanedRooms = new Set(orphanedRooms);
this.rootSpaces = rootSpaces; this.rootSpaces = rootSpaces;
this.parentMap = backrefs; this.parentMap = backrefs;
@ -320,25 +315,6 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
this.rebuild(); this.rebuild();
} }
private showInHomeSpace = (room: Room) => {
if (room.isSpaceRoom()) return false;
return !this.parentMap.get(room.roomId)?.size // put all orphaned rooms in the Home Space
|| DMRoomMap.shared().getUserIdForRoomId(room.roomId) // put all DMs in the Home Space
|| RoomListStore.instance.getTagsForRoom(room).includes(DefaultTagID.Favourite) // show all favourites
};
// Update a given room due to its tag changing (e.g DM-ness or Fav-ness)
// This can only change whether it shows up in the HOME_SPACE or not
private onRoomUpdate = (room: Room) => {
if (this.showInHomeSpace(room)) {
this.spaceFilteredRooms.get(HOME_SPACE)?.add(room.roomId);
this.emit(HOME_SPACE);
} else if (!this.orphanedRooms.has(room.roomId)) {
this.spaceFilteredRooms.get(HOME_SPACE)?.delete(room.roomId);
this.emit(HOME_SPACE);
}
};
private onSpaceMembersChange = (ev: MatrixEvent) => { private onSpaceMembersChange = (ev: MatrixEvent) => {
// skip this update if we do not have a DM with this user // skip this update if we do not have a DM with this user
if (DMRoomMap.shared().getDMRoomsForUserId(ev.getStateKey()).length < 1) return; if (DMRoomMap.shared().getDMRoomsForUserId(ev.getStateKey()).length < 1) return;
@ -352,16 +328,6 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
const oldFilteredRooms = this.spaceFilteredRooms; const oldFilteredRooms = this.spaceFilteredRooms;
this.spaceFilteredRooms = new Map(); this.spaceFilteredRooms = new Map();
// put all room invites in the Home Space
const invites = visibleRooms.filter(r => !r.isSpaceRoom() && r.getMyMembership() === "invite");
this.spaceFilteredRooms.set(HOME_SPACE, new Set<string>(invites.map(room => room.roomId)));
visibleRooms.forEach(room => {
if (this.showInHomeSpace(room)) {
this.spaceFilteredRooms.get(HOME_SPACE).add(room.roomId);
}
});
this.rootSpaces.forEach(s => { this.rootSpaces.forEach(s => {
// traverse each space tree in DFS to build up the supersets as you go up, // traverse each space tree in DFS to build up the supersets as you go up,
// reusing results from like subtrees. // reusing results from like subtrees.
@ -408,13 +374,8 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
// Update NotificationStates // Update NotificationStates
this.getNotificationState(s)?.setRooms(visibleRooms.filter(room => { this.getNotificationState(s)?.setRooms(visibleRooms.filter(room => {
if (roomIds.has(room.roomId)) { if (roomIds.has(room.roomId)) {
// Don't aggregate notifications for DMs except in the Home Space return !DMRoomMap.shared().getUserIdForRoomId(room.roomId)
if (s !== HOME_SPACE) { || RoomListStore.instance.getTagsForRoom(room).includes(DefaultTagID.Favourite);
return !DMRoomMap.shared().getUserIdForRoomId(room.roomId)
|| RoomListStore.instance.getTagsForRoom(room).includes(DefaultTagID.Favourite);
}
return true;
} }
return false; return false;
@ -475,8 +436,6 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
// TODO confirm this after implementing parenting behaviour // TODO confirm this after implementing parenting behaviour
if (room.isSpaceRoom()) { if (room.isSpaceRoom()) {
this.onSpaceUpdate(); this.onSpaceUpdate();
} else {
this.onRoomUpdate(room);
} }
this.emit(room.roomId); this.emit(room.roomId);
break; break;
@ -489,38 +448,8 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
} }
}; };
private onRoomAccountData = (ev: MatrixEvent, room: Room, lastEvent?: MatrixEvent) => {
if (ev.getType() === EventType.Tag && !room.isSpaceRoom()) {
// If the room was in favourites and now isn't or the opposite then update its position in the trees
const oldTags = lastEvent?.getContent()?.tags || {};
const newTags = ev.getContent()?.tags || {};
if (!!oldTags[DefaultTagID.Favourite] !== !!newTags[DefaultTagID.Favourite]) {
this.onRoomUpdate(room);
}
}
}
private onAccountData = (ev: MatrixEvent, lastEvent: MatrixEvent) => {
if (ev.getType() === EventType.Direct) {
const lastContent = lastEvent.getContent();
const content = ev.getContent();
const diff = objectDiff<Record<string, string[]>>(lastContent, content);
// filter out keys which changed by reference only by checking whether the sets differ
const changed = diff.changed.filter(k => arrayHasDiff(lastContent[k], content[k]));
// DM tag changes, refresh relevant rooms
new Set([...diff.added, ...diff.removed, ...changed]).forEach(roomId => {
const room = this.matrixClient?.getRoom(roomId);
if (room) {
this.onRoomUpdate(room);
}
});
}
};
protected async reset() { protected async reset() {
this.rootSpaces = []; this.rootSpaces = [];
this.orphanedRooms = new Set();
this.parentMap = new EnhancedMap(); this.parentMap = new EnhancedMap();
this.notificationStateMap = new Map(); this.notificationStateMap = new Map();
this.spaceFilteredRooms = new Map(); this.spaceFilteredRooms = new Map();
@ -535,8 +464,6 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
this.matrixClient.removeListener("Room", this.onRoom); this.matrixClient.removeListener("Room", this.onRoom);
this.matrixClient.removeListener("Room.myMembership", this.onRoom); this.matrixClient.removeListener("Room.myMembership", this.onRoom);
this.matrixClient.removeListener("RoomState.events", this.onRoomState); this.matrixClient.removeListener("RoomState.events", this.onRoomState);
this.matrixClient.removeListener("Room.accountData", this.onRoomAccountData);
this.matrixClient.removeListener("accountData", this.onAccountData);
} }
await this.reset(); await this.reset();
} }
@ -546,8 +473,6 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
this.matrixClient.on("Room", this.onRoom); this.matrixClient.on("Room", this.onRoom);
this.matrixClient.on("Room.myMembership", this.onRoom); this.matrixClient.on("Room.myMembership", this.onRoom);
this.matrixClient.on("RoomState.events", this.onRoomState); this.matrixClient.on("RoomState.events", this.onRoomState);
this.matrixClient.on("Room.accountData", this.onRoomAccountData);
this.matrixClient.on("accountData", this.onAccountData);
await this.onSpaceUpdate(); // trigger an initial update await this.onSpaceUpdate(); // trigger an initial update
@ -602,7 +527,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
} }
} }
public getNotificationState(key: SpaceKey): SpaceNotificationState { public getNotificationState(key: string): SpaceNotificationState {
if (this.notificationStateMap.has(key)) { if (this.notificationStateMap.has(key)) {
return this.notificationStateMap.get(key); return this.notificationStateMap.get(key);
} }

View file

@ -601,11 +601,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
&& (!SettingsStore.getValue("feature_spaces") || !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)) {
@ -679,10 +675,6 @@ export class RoomListStoreClass extends AsyncStoreWithClient<IState> {
if (this.algorithm) { if (this.algorithm) {
this.algorithm.addFilterCondition(filter); this.algorithm.addFilterCondition(filter);
} }
// Runtime filters with spaces disable prefiltering for the search all spaces effect
if (SettingsStore.getValue("feature_spaces")) {
promise = this.recalculatePrefiltering();
}
} }
promise.then(() => this.updateFn.trigger()); promise.then(() => this.updateFn.trigger());
} }
@ -706,10 +698,6 @@ export class RoomListStoreClass extends AsyncStoreWithClient<IState> {
if (this.algorithm) { if (this.algorithm) {
this.algorithm.removeFilterCondition(filter); this.algorithm.removeFilterCondition(filter);
// Runtime filters with spaces disable prefiltering for the search all spaces effect
if (SettingsStore.getValue("feature_spaces")) {
promise = this.recalculatePrefiltering();
}
} }
} }
idx = this.prefilterConditions.indexOf(filter); idx = this.prefilterConditions.indexOf(filter);

View file

@ -24,26 +24,34 @@ import SpaceStore, { UPDATE_SELECTED_SPACE } from "../SpaceStore";
* Watches for changes in spaces to manage the filter on the provided RoomListStore * Watches for changes in spaces to manage the filter on the provided RoomListStore
*/ */
export class SpaceWatcher { export class SpaceWatcher {
private filter = new SpaceFilterCondition(); private filter: SpaceFilterCondition;
private activeSpace: Room = SpaceStore.instance.activeSpace; private activeSpace: Room = SpaceStore.instance.activeSpace;
constructor(private store: RoomListStoreClass) { constructor(private store: RoomListStoreClass) {
this.updateFilter(); // get the filter into a consistent state
store.addFilter(this.filter);
SpaceStore.instance.on(UPDATE_SELECTED_SPACE, this.onSelectedSpaceUpdated); SpaceStore.instance.on(UPDATE_SELECTED_SPACE, this.onSelectedSpaceUpdated);
} }
private onSelectedSpaceUpdated = (activeSpace: Room) => { private onSelectedSpaceUpdated = (activeSpace?: Room) => {
this.activeSpace = activeSpace; this.activeSpace = activeSpace;
this.updateFilter();
if (this.filter) {
if (activeSpace) {
this.updateFilter();
} else {
this.store.removeFilter(this.filter);
this.filter = null;
}
} else if (activeSpace) {
this.filter = new SpaceFilterCondition();
this.updateFilter();
this.store.addFilter(this.filter);
}
}; };
private updateFilter = () => { private updateFilter = () => {
if (this.activeSpace) { SpaceStore.instance.traverseSpace(this.activeSpace.roomId, roomId => {
SpaceStore.instance.traverseSpace(this.activeSpace.roomId, roomId => { this.store.matrixClient?.getRoom(roomId)?.loadMembersIfNeeded();
this.store.matrixClient?.getRoom(roomId)?.loadMembersIfNeeded(); });
});
}
this.filter.updateSpace(this.activeSpace); this.filter.updateSpace(this.activeSpace);
}; };
} }

View file

@ -19,7 +19,7 @@ import { Room } from "matrix-js-sdk/src/models/room";
import { FILTER_CHANGED, FilterKind, IFilterCondition } from "./IFilterCondition"; import { FILTER_CHANGED, FilterKind, IFilterCondition } from "./IFilterCondition";
import { IDestroyable } from "../../../utils/IDestroyable"; import { IDestroyable } from "../../../utils/IDestroyable";
import SpaceStore, {HOME_SPACE} from "../../SpaceStore"; import SpaceStore from "../../SpaceStore";
import { setHasDiff } from "../../../utils/sets"; import { setHasDiff } from "../../../utils/sets";
/** /**
@ -55,10 +55,12 @@ export class SpaceFilterCondition extends EventEmitter implements IFilterConditi
} }
}; };
private getSpaceEventKey = (space: Room | null) => space ? space.roomId : HOME_SPACE; private getSpaceEventKey = (space: Room) => space.roomId;
public updateSpace(space: Room) { public updateSpace(space: Room) {
SpaceStore.instance.off(this.getSpaceEventKey(this.space), this.onStoreUpdate); if (this.space) {
SpaceStore.instance.off(this.getSpaceEventKey(this.space), this.onStoreUpdate);
}
SpaceStore.instance.on(this.getSpaceEventKey(this.space = space), this.onStoreUpdate); SpaceStore.instance.on(this.getSpaceEventKey(this.space = space), this.onStoreUpdate);
this.onStoreUpdate(); // initial update from the change to the space this.onStoreUpdate(); // initial update from the change to the space
} }