Replace ChaoticAlgorithm for tag sorting with deterministic behaviour

aka: implement the algorithms.
This commit is contained in:
Travis Ralston 2020-05-14 14:06:48 -06:00
parent 6cb1efc1a4
commit 91a997da14
3 changed files with 92 additions and 7 deletions

View file

@ -17,13 +17,16 @@ limitations under the License.
import { Room } from "matrix-js-sdk/src/models/room";
import { TagID } from "../../models";
import { IAlgorithm } from "./IAlgorithm";
import { MatrixClientPeg } from "../../../../MatrixClientPeg";
import * as Unread from "../../../../Unread";
/**
* A demonstration to test the API surface.
* TODO: Remove this before landing
* Sorts rooms according to the browser's determination of alphabetic.
*/
export class ChaoticAlgorithm implements IAlgorithm {
export class AlphabeticAlgorithm implements IAlgorithm {
public async sortRooms(rooms: Room[], tagId: TagID): Promise<Room[]> {
return rooms;
return rooms.sort((a, b) => {
return a.name.localeCompare(b.name);
});
}
}

View file

@ -0,0 +1,81 @@
/*
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 { Room } from "matrix-js-sdk/src/models/room";
import { TagID } from "../../models";
import { IAlgorithm } from "./IAlgorithm";
import { MatrixClientPeg } from "../../../../MatrixClientPeg";
import * as Unread from "../../../../Unread";
/**
* Sorts rooms according to the last event's timestamp in each room that seems
* useful to the user.
*/
export class RecentAlgorithm implements IAlgorithm {
public async sortRooms(rooms: Room[], tagId: TagID): Promise<Room[]> {
// We cache the timestamp lookup to avoid iterating forever on the timeline
// of events. This cache only survives a single sort though.
// We wouldn't need this if `.sort()` didn't constantly try and compare all
// of the rooms to each other.
// TODO: We could probably improve the sorting algorithm here by finding changes.
// For example, if we spent a little bit of time to determine which elements have
// actually changed (probably needs to be done higher up?) then we could do an
// insertion sort or similar on the limited set of changes.
const tsCache: { [roomId: string]: number } = {};
const getLastTs = (r: Room) => {
if (tsCache[r.roomId]) {
return tsCache[r.roomId];
}
const ts = (() => {
// Apparently we can have rooms without timelines, at least under testing
// environments. Just return MAX_INT when this happens.
if (!r || !r.timeline) {
return Number.MAX_SAFE_INTEGER;
}
for (let i = r.timeline.length - 1; i >= 0; --i) {
const ev = r.timeline[i];
if (!ev.getTs()) continue; // skip events that don't have timestamps (tests only?)
// TODO: Don't assume we're using the same client as the peg
if (ev.getSender() === MatrixClientPeg.get().getUserId()
|| Unread.eventTriggersUnreadCount(ev)) {
return ev.getTs();
}
}
// we might only have events that don't trigger the unread indicator,
// in which case use the oldest event even if normally it wouldn't count.
// This is better than just assuming the last event was forever ago.
if (r.timeline.length && r.timeline[0].getTs()) {
return r.timeline[0].getTs();
} else {
return Number.MAX_SAFE_INTEGER;
}
})();
tsCache[r.roomId] = ts;
return ts;
};
return rooms.sort((a, b) => {
return getLastTs(a) - getLastTs(b);
});
}
}

View file

@ -14,16 +14,17 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import { ChaoticAlgorithm } from "./ChaoticAlgorithm";
import { SortAlgorithm } from "../models";
import { ManualAlgorithm } from "./ManualAlgorithm";
import { IAlgorithm } from "./IAlgorithm";
import { TagID } from "../../models";
import { Room } from "matrix-js-sdk/src/models/room";
import { RecentAlgorithm } from "./RecentAlgorithm";
import { AlphabeticAlgorithm } from "./AlphabeticAlgorithm";
const ALGORITHM_INSTANCES: { [algorithm in SortAlgorithm]: IAlgorithm } = {
[SortAlgorithm.Recent]: new ChaoticAlgorithm(),
[SortAlgorithm.Alphabetic]: new ChaoticAlgorithm(),
[SortAlgorithm.Recent]: new RecentAlgorithm(),
[SortAlgorithm.Alphabetic]: new AlphabeticAlgorithm(),
[SortAlgorithm.Manual]: new ManualAlgorithm(),
};