Dumb down list algorithms in favour of smarter tags
This commit is a bit involved, as it factors the tag specific handling out of `/list-ordering` (and moves the `Algorithm` class one higher as a result), leaving it in the `Algorithm`. The algorithms for list ordering now only know how to handle a single tag, and this is managed by the `Algorithm` class - which is also no longer the base class for the list ordering. The list ordering algorithms now inherit from a generic `OrderingAlgorithm` base class which handles some rudimentary things. Overall the logic hasn't changed much: the tag-specific stuff has been moved into the `Algorithm`, and the list ordering algorithms essentially just removed the iteration on tags. The `RoomListStore2` still shovels a bunch of information over to the `Algorithm`, which can lead to an awkward code flow however this commit is meant to keep the number of surfaces touched to a minimum. The RoomListStore has also gained the ability to set per-list (tag) ordering and sorting, which is required for the new room list. The assumption that it defaults from the account-level settings is not reviewed by design, yet. This decision is deferred.
This commit is contained in:
parent
52b26deb2e
commit
fd029e8e80
7 changed files with 374 additions and 234 deletions
|
@ -17,25 +17,21 @@ limitations under the License.
|
|||
|
||||
import { MatrixClient } from "matrix-js-sdk/src/client";
|
||||
import SettingsStore from "../../settings/SettingsStore";
|
||||
import { DefaultTagID, OrderedDefaultTagIDs, RoomUpdateCause, TagID } from "./models";
|
||||
import { Algorithm, LIST_UPDATED_EVENT } from "./algorithms/list-ordering/Algorithm";
|
||||
import { OrderedDefaultTagIDs, RoomUpdateCause, TagID } from "./models";
|
||||
import TagOrderStore from "../TagOrderStore";
|
||||
import { AsyncStore } from "../AsyncStore";
|
||||
import { Room } from "matrix-js-sdk/src/models/room";
|
||||
import { ITagMap, ITagSortingMap, ListAlgorithm, SortAlgorithm } from "./algorithms/models";
|
||||
import { getListAlgorithmInstance } from "./algorithms/list-ordering";
|
||||
import { IListOrderingMap, ITagMap, ITagSortingMap, ListAlgorithm, SortAlgorithm } from "./algorithms/models";
|
||||
import { ActionPayload } from "../../dispatcher/payloads";
|
||||
import defaultDispatcher from "../../dispatcher/dispatcher";
|
||||
import { readReceiptChangeIsFor } from "../../utils/read-receipts";
|
||||
import { IFilterCondition } from "./filters/IFilterCondition";
|
||||
import { TagWatcher } from "./TagWatcher";
|
||||
import RoomViewStore from "../RoomViewStore";
|
||||
import { Algorithm, LIST_UPDATED_EVENT } from "./algorithms/Algorithm";
|
||||
|
||||
interface IState {
|
||||
tagsEnabled?: boolean;
|
||||
|
||||
preferredSort?: SortAlgorithm;
|
||||
preferredAlgorithm?: ListAlgorithm;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -48,7 +44,7 @@ export class RoomListStore2 extends AsyncStore<ActionPayload> {
|
|||
private _matrixClient: MatrixClient;
|
||||
private initialListsGenerated = false;
|
||||
private enabled = false;
|
||||
private algorithm: Algorithm;
|
||||
private algorithm = new Algorithm();
|
||||
private filterConditions: IFilterCondition[] = [];
|
||||
private tagWatcher = new TagWatcher(this);
|
||||
|
||||
|
@ -64,6 +60,7 @@ export class RoomListStore2 extends AsyncStore<ActionPayload> {
|
|||
this.checkEnabled();
|
||||
for (const settingName of this.watchedSettings) SettingsStore.monitorSetting(settingName, null);
|
||||
RoomViewStore.addListener(this.onRVSUpdate);
|
||||
this.algorithm.on(LIST_UPDATED_EVENT, this.onAlgorithmListUpdated);
|
||||
}
|
||||
|
||||
public get orderedLists(): ITagMap {
|
||||
|
@ -85,14 +82,10 @@ export class RoomListStore2 extends AsyncStore<ActionPayload> {
|
|||
|
||||
private async readAndCacheSettingsFromStore() {
|
||||
const tagsEnabled = SettingsStore.isFeatureEnabled("feature_custom_tags");
|
||||
const orderByImportance = SettingsStore.getValue("RoomList.orderByImportance");
|
||||
const orderAlphabetically = SettingsStore.getValue("RoomList.orderAlphabetically");
|
||||
await this.updateState({
|
||||
tagsEnabled,
|
||||
preferredSort: orderAlphabetically ? SortAlgorithm.Alphabetic : SortAlgorithm.Recent,
|
||||
preferredAlgorithm: orderByImportance ? ListAlgorithm.Importance : ListAlgorithm.Natural,
|
||||
});
|
||||
this.setAlgorithmClass();
|
||||
await this.updateAlgorithmInstances();
|
||||
}
|
||||
|
||||
private onRVSUpdate = () => {
|
||||
|
@ -259,17 +252,57 @@ export class RoomListStore2 extends AsyncStore<ActionPayload> {
|
|||
}
|
||||
}
|
||||
|
||||
private getSortAlgorithmFor(tagId: TagID): SortAlgorithm {
|
||||
switch (tagId) {
|
||||
case DefaultTagID.Invite:
|
||||
case DefaultTagID.Untagged:
|
||||
case DefaultTagID.Archived:
|
||||
case DefaultTagID.LowPriority:
|
||||
case DefaultTagID.DM:
|
||||
return this.state.preferredSort;
|
||||
case DefaultTagID.Favourite:
|
||||
default:
|
||||
return SortAlgorithm.Manual;
|
||||
public async setTagSorting(tagId: TagID, sort: SortAlgorithm) {
|
||||
await this.algorithm.setTagSorting(tagId, sort);
|
||||
localStorage.setItem(`mx_tagSort_${tagId}`, sort);
|
||||
}
|
||||
|
||||
public getTagSorting(tagId: TagID): SortAlgorithm {
|
||||
return this.algorithm.getTagSorting(tagId);
|
||||
}
|
||||
|
||||
// noinspection JSMethodCanBeStatic
|
||||
private getStoredTagSorting(tagId: TagID): SortAlgorithm {
|
||||
return <SortAlgorithm>localStorage.getItem(`mx_tagSort_${tagId}`);
|
||||
}
|
||||
|
||||
public async setListOrder(tagId: TagID, order: ListAlgorithm) {
|
||||
await this.algorithm.setListOrdering(tagId, order);
|
||||
localStorage.setItem(`mx_listOrder_${tagId}`, order);
|
||||
}
|
||||
|
||||
public getListOrder(tagId: TagID): ListAlgorithm {
|
||||
return this.algorithm.getListOrdering(tagId);
|
||||
}
|
||||
|
||||
// noinspection JSMethodCanBeStatic
|
||||
private getStoredListOrder(tagId: TagID): ListAlgorithm {
|
||||
return <ListAlgorithm>localStorage.getItem(`mx_listOrder_${tagId}`);
|
||||
}
|
||||
|
||||
private async updateAlgorithmInstances() {
|
||||
const orderByImportance = SettingsStore.getValue("RoomList.orderByImportance");
|
||||
const orderAlphabetically = SettingsStore.getValue("RoomList.orderAlphabetically");
|
||||
|
||||
const defaultSort = orderAlphabetically ? SortAlgorithm.Alphabetic : SortAlgorithm.Recent;
|
||||
const defaultOrder = orderByImportance ? ListAlgorithm.Importance : ListAlgorithm.Natural;
|
||||
|
||||
for (const tag of Object.keys(this.orderedLists)) {
|
||||
const definedSort = this.getTagSorting(tag);
|
||||
const definedOrder = this.getListOrder(tag);
|
||||
|
||||
const storedSort = this.getStoredTagSorting(tag);
|
||||
const storedOrder = this.getStoredListOrder(tag);
|
||||
|
||||
const tagSort = storedSort ? storedSort : (definedSort ? definedSort : defaultSort);
|
||||
const listOrder = storedOrder ? storedOrder : (definedOrder ? definedOrder : defaultOrder);
|
||||
|
||||
if (tagSort !== definedSort) {
|
||||
await this.setTagSorting(tag, tagSort);
|
||||
}
|
||||
if (listOrder !== definedOrder) {
|
||||
await this.setListOrder(tag, listOrder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -279,15 +312,6 @@ export class RoomListStore2 extends AsyncStore<ActionPayload> {
|
|||
await super.updateState(newState);
|
||||
}
|
||||
|
||||
private setAlgorithmClass() {
|
||||
if (this.algorithm) {
|
||||
this.algorithm.off(LIST_UPDATED_EVENT, this.onAlgorithmListUpdated);
|
||||
}
|
||||
this.algorithm = getListAlgorithmInstance(this.state.preferredAlgorithm);
|
||||
this.algorithm.setFilterConditions(this.filterConditions);
|
||||
this.algorithm.on(LIST_UPDATED_EVENT, this.onAlgorithmListUpdated);
|
||||
}
|
||||
|
||||
private onAlgorithmListUpdated = () => {
|
||||
console.log("Underlying algorithm has triggered a list update - refiring");
|
||||
this.emit(LISTS_UPDATE_EVENT, this);
|
||||
|
@ -296,9 +320,11 @@ export class RoomListStore2 extends AsyncStore<ActionPayload> {
|
|||
private async regenerateAllLists() {
|
||||
console.warn("Regenerating all room lists");
|
||||
|
||||
const tags: ITagSortingMap = {};
|
||||
const sorts: ITagSortingMap = {};
|
||||
const orders: IListOrderingMap = {};
|
||||
for (const tagId of OrderedDefaultTagIDs) {
|
||||
tags[tagId] = this.getSortAlgorithmFor(tagId);
|
||||
sorts[tagId] = this.getStoredTagSorting(tagId) || SortAlgorithm.Alphabetic;
|
||||
orders[tagId] = this.getStoredListOrder(tagId) || ListAlgorithm.Natural;
|
||||
}
|
||||
|
||||
if (this.state.tagsEnabled) {
|
||||
|
@ -307,7 +333,7 @@ export class RoomListStore2 extends AsyncStore<ActionPayload> {
|
|||
console.log("rtags", roomTags);
|
||||
}
|
||||
|
||||
await this.algorithm.populateTags(tags);
|
||||
await this.algorithm.populateTags(sorts, orders);
|
||||
await this.algorithm.setKnownRooms(this.matrixClient.getRooms());
|
||||
|
||||
this.initialListsGenerated = true;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue