Support prioritized room list filters
This is to fix an issue where when using both the community filter panel and the search box it's an AND rather than further refining the results. This makes the search box further refine the community filter panel results.
This commit is contained in:
parent
ae1d14d29f
commit
3fcd5505b3
6 changed files with 134 additions and 9 deletions
|
@ -20,9 +20,11 @@ import { isNullOrUndefined } from "matrix-js-sdk/src/utils";
|
|||
import { EffectiveMembership, splitRoomsByMembership } from "../../membership";
|
||||
import { ITagMap, ITagSortingMap } from "../models";
|
||||
import DMRoomMap from "../../../../utils/DMRoomMap";
|
||||
import { FILTER_CHANGED, IFilterCondition } from "../../filters/IFilterCondition";
|
||||
import { FILTER_CHANGED, FilterPriority, IFilterCondition } from "../../filters/IFilterCondition";
|
||||
import { EventEmitter } from "events";
|
||||
import { UPDATE_EVENT } from "../../../AsyncStore";
|
||||
import { ArrayUtil } from "../../../../utils/arrays";
|
||||
import { getEnumValues } from "../../../../utils/enums";
|
||||
|
||||
// TODO: Add locking support to avoid concurrent writes?
|
||||
|
||||
|
@ -184,22 +186,33 @@ export abstract class Algorithm extends EventEmitter {
|
|||
}
|
||||
|
||||
console.warn("Recalculating filtered room list");
|
||||
const allowedByFilters = new Set<Room>();
|
||||
const filters = Array.from(this.allowedByFilter.keys());
|
||||
const orderedFilters = new ArrayUtil(filters)
|
||||
.groupBy(f => f.relativePriority)
|
||||
.orderBy(getEnumValues(FilterPriority))
|
||||
.value;
|
||||
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];
|
||||
const remainingRooms = rooms.map(r => r).filter(r => !allowedByFilters.has(r));
|
||||
const allowedRoomsInThisTag = [];
|
||||
for (const filter of filters) {
|
||||
let remainingRooms = rooms.map(r => r);
|
||||
let allowedRoomsInThisTag = [];
|
||||
let lastFilterPriority = orderedFilters[0].relativePriority;
|
||||
for (const filter of orderedFilters) {
|
||||
if (filter.relativePriority !== lastFilterPriority) {
|
||||
// Every time the filter changes priority, we want more specific filtering.
|
||||
// To accomplish that, reset the variables to make it look like the process
|
||||
// has started over, but using the filtered rooms as the seed.
|
||||
remainingRooms = allowedRoomsInThisTag;
|
||||
allowedRoomsInThisTag = [];
|
||||
lastFilterPriority = filter.relativePriority;
|
||||
}
|
||||
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);
|
||||
allowedByFilters.add(room);
|
||||
allowedRoomsInThisTag.push(room);
|
||||
}
|
||||
}
|
||||
|
@ -207,7 +220,8 @@ export abstract class Algorithm extends EventEmitter {
|
|||
console.log(`[DEBUG] ${newMap[tagId].length}/${rooms.length} rooms filtered into ${tagId}`);
|
||||
}
|
||||
|
||||
this.allowedRoomsByFilters = allowedByFilters;
|
||||
const allowedRooms = Object.values(newMap).reduce((rv, v) => { rv.push(...v); return rv; }, <Room[]>[]);
|
||||
this.allowedRoomsByFilters = new Set(allowedRooms);
|
||||
this.filteredRooms = newMap;
|
||||
this.emit(LIST_UPDATED_EVENT);
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import { Room } from "matrix-js-sdk/src/models/room";
|
||||
import { FILTER_CHANGED, IFilterCondition } from "./IFilterCondition";
|
||||
import { FILTER_CHANGED, FilterPriority, IFilterCondition } from "./IFilterCondition";
|
||||
import { Group } from "matrix-js-sdk/src/models/group";
|
||||
import { EventEmitter } from "events";
|
||||
import GroupStore from "../../GroupStore";
|
||||
|
@ -37,6 +37,11 @@ export class CommunityFilterCondition extends EventEmitter implements IFilterCon
|
|||
this.onStoreUpdate(); // trigger a false update to seed the store
|
||||
}
|
||||
|
||||
public get relativePriority(): FilterPriority {
|
||||
// Lowest priority so we can coarsely find rooms.
|
||||
return FilterPriority.Lowest;
|
||||
}
|
||||
|
||||
public isVisible(room: Room): boolean {
|
||||
return this.roomIds.includes(room.roomId);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,12 @@ import { EventEmitter } from "events";
|
|||
|
||||
export const FILTER_CHANGED = "filter_changed";
|
||||
|
||||
export enum FilterPriority {
|
||||
Lowest,
|
||||
// in the middle would be Low, Normal, and High if we had a need
|
||||
Highest,
|
||||
}
|
||||
|
||||
/**
|
||||
* A filter condition for the room list, determining if a room
|
||||
* should be shown or not.
|
||||
|
@ -32,6 +38,12 @@ export const FILTER_CHANGED = "filter_changed";
|
|||
* as a change in the user's input), this emits FILTER_CHANGED.
|
||||
*/
|
||||
export interface IFilterCondition extends EventEmitter {
|
||||
/**
|
||||
* The relative priority that this filter should be applied with.
|
||||
* Lower priorities get applied first.
|
||||
*/
|
||||
relativePriority: FilterPriority;
|
||||
|
||||
/**
|
||||
* Determines if a given room should be visible under this
|
||||
* condition.
|
||||
|
|
|
@ -15,7 +15,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import { Room } from "matrix-js-sdk/src/models/room";
|
||||
import { FILTER_CHANGED, IFilterCondition } from "./IFilterCondition";
|
||||
import { FILTER_CHANGED, FilterPriority, IFilterCondition } from "./IFilterCondition";
|
||||
import { EventEmitter } from "events";
|
||||
|
||||
/**
|
||||
|
@ -29,6 +29,11 @@ export class NameFilterCondition extends EventEmitter implements IFilterConditio
|
|||
super();
|
||||
}
|
||||
|
||||
public get relativePriority(): FilterPriority {
|
||||
// We want this one to be at the highest priority so it can search within other filters.
|
||||
return FilterPriority.Highest;
|
||||
}
|
||||
|
||||
public get search(): string {
|
||||
return this._search;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue