Implement sync v3 sorting

This commit is contained in:
Kegan Dougal 2021-11-30 13:24:08 +00:00
parent 29c60eb699
commit 956b4a9b96
5 changed files with 43 additions and 9 deletions

View file

@ -39,7 +39,8 @@ export class SessionViewModel extends ViewModel {
}))); })));
this._leftPanelViewModel = this.track(new LeftPanelViewModel(this.childOptions({ this._leftPanelViewModel = this.track(new LeftPanelViewModel(this.childOptions({
invites: this._sessionContainer.session.invites, invites: this._sessionContainer.session.invites,
rooms: this._sessionContainer.session.rooms rooms: this._sessionContainer.session.rooms,
compareFn: this._sessionContainer.sync.compare.bind(this._sessionContainer.sync),
}))); })));
this._settingsViewModel = null; this._settingsViewModel = null;
this._roomViewModelObservable = null; this._roomViewModelObservable = null;

View file

@ -26,7 +26,7 @@ import { PlaceholderRoomTileViewModel } from "./PlaceholderRoomTileViewModel.js"
export class LeftPanelViewModel extends ViewModel { export class LeftPanelViewModel extends ViewModel {
constructor(options) { constructor(options) {
super(options); super(options);
const {rooms, invites} = options; const {rooms, invites, compareFn} = options;
this._tileViewModelsMap = this._mapTileViewModels(rooms, invites); this._tileViewModelsMap = this._mapTileViewModels(rooms, invites);
this._tileViewModelsFilterMap = new ApplyMap(this._tileViewModelsMap); this._tileViewModelsFilterMap = new ApplyMap(this._tileViewModelsMap);
this._tileViewModels = this._tileViewModelsFilterMap.sortValues((a, b) => a.compare(b)); this._tileViewModels = this._tileViewModelsFilterMap.sortValues((a, b) => a.compare(b));
@ -34,6 +34,7 @@ export class LeftPanelViewModel extends ViewModel {
this._setupNavigation(); this._setupNavigation();
this._closeUrl = this.urlCreator.urlForSegment("session"); this._closeUrl = this.urlCreator.urlForSegment("session");
this._settingsUrl = this.urlCreator.urlForSegment("settings"); this._settingsUrl = this.urlCreator.urlForSegment("settings");
this._compareFn = compareFn;
} }
_mapTileViewModels(rooms, invites) { _mapTileViewModels(rooms, invites) {
@ -45,7 +46,11 @@ export class LeftPanelViewModel extends ViewModel {
} else if (roomOrInvite.isPlaceholder) { } else if (roomOrInvite.isPlaceholder) {
vm = new PlaceholderRoomTileViewModel(this.childOptions({room: roomOrInvite, emitChange})); vm = new PlaceholderRoomTileViewModel(this.childOptions({room: roomOrInvite, emitChange}));
} else { } else {
vm = new RoomTileViewModel(this.childOptions({room: roomOrInvite, emitChange})); vm = new RoomTileViewModel(this.childOptions({
room: roomOrInvite,
compareFn: this._compareFn,
emitChange,
}));
} }
const isOpen = this.navigation.path.get("room")?.value === roomOrInvite.id; const isOpen = this.navigation.path.get("room")?.value === roomOrInvite.id;
if (isOpen) { if (isOpen) {

View file

@ -20,9 +20,10 @@ import {BaseTileViewModel} from "./BaseTileViewModel.js";
export class RoomTileViewModel extends BaseTileViewModel { export class RoomTileViewModel extends BaseTileViewModel {
constructor(options) { constructor(options) {
super(options); super(options);
const {room} = options; const {room, compareFn} = options;
this._room = room; this._room = room;
this._url = this.urlCreator.openRoomActionUrl(this._room.id); this._url = this.urlCreator.openRoomActionUrl(this._room.id);
this._compareFn = compareFn;
} }
get kind() { get kind() {
@ -34,6 +35,8 @@ export class RoomTileViewModel extends BaseTileViewModel {
} }
compare(other) { compare(other) {
return this._compareFn(this._room.id, other._room.id);
const parentComparison = super.compare(other); const parentComparison = super.compare(other);
if (parentComparison !== 0) { if (parentComparison !== 0) {
return parentComparison; return parentComparison;

View file

@ -97,8 +97,11 @@ interface RoomResponse {
}; };
type IndexToRoomId = { type IndexToRoomId = {
[index: string]: string; [index: number]: string;
}; };
type RoomIdToIndex = {
[roomId: string]: number;
}
export class Sync3 { export class Sync3 {
private hsApi: HomeServerApi; private hsApi: HomeServerApi;
@ -110,6 +113,7 @@ export class Sync3 {
// sync v3 specific: contains the sliding window ranges to request // sync v3 specific: contains the sliding window ranges to request
private ranges: number[][]; private ranges: number[][];
private roomIndexToRoomId: IndexToRoomId; private roomIndexToRoomId: IndexToRoomId;
private roomIdToRoomIndex: RoomIdToIndex;
public error?: any; public error?: any;
public status: ObservableValue<SyncStatus>; public status: ObservableValue<SyncStatus>;
@ -126,6 +130,7 @@ export class Sync3 {
// Hydrogen only has 1 list currently (no DM section) so we only need 1 range // Hydrogen only has 1 list currently (no DM section) so we only need 1 range
this.ranges = [[0, 99]]; this.ranges = [[0, 99]];
this.roomIndexToRoomId = {}; this.roomIndexToRoomId = {};
this.roomIdToRoomIndex = {};
console.log("session", session); console.log("session", session);
console.log("storage", storage); console.log("storage", storage);
} }
@ -152,6 +157,21 @@ export class Sync3 {
} }
} }
compare(roomIdA: string, roomIdB: string) {
if (roomIdA === roomIdB) {
return 0;
}
const indexA = this.roomIdToRoomIndex[roomIdA];
const indexB = this.roomIdToRoomIndex[roomIdB];
if (indexA === undefined || indexB === undefined) {
console.error("sync3 cannot compare: missing indices for rooms", roomIdA, roomIdB, indexA, indexB);
}
if (indexA < indexB) {
return -1;
}
return 1;
}
// The purpose of this function is to do repeated /sync calls and call processResponse. It doesn't // The purpose of this function is to do repeated /sync calls and call processResponse. It doesn't
// know or care how to handle the response, it only cares about the position and retries. // know or care how to handle the response, it only cares about the position and retries.
private async syncLoop(pos?: number) { private async syncLoop(pos?: number) {
@ -298,6 +318,14 @@ export class Sync3 {
} }
await syncTxn.complete(log); await syncTxn.complete(log);
// atomically move all the rooms to their new positions
this.roomIndexToRoomId = indexToRoom;
this.roomIdToRoomIndex = {};
Object.keys(indexToRoom).forEach((indexStr) => {
const index = Number(indexStr);
this.roomIdToRoomIndex[indexToRoom[index]] = index;
});
// update in-memory structs // update in-memory structs
// this.session.afterSync(); // ??? // this.session.afterSync(); // ???
@ -317,10 +345,6 @@ export class Sync3 {
} }
}), []); }), []);
}); });
// instantly move all the rooms to their new positions
this.roomIndexToRoomId = indexToRoom;
} }
// The purpose of this function is to process the response `ops` array by modifying the current // The purpose of this function is to process the response `ops` array by modifying the current

View file

@ -104,6 +104,7 @@
navigation: navigation, navigation: navigation,
urlCreator: urlRouter, urlCreator: urlRouter,
platform: platform, platform: platform,
compareFn: syncer.compare.bind(syncer),
}); });
leftPanel.loadRoomRange = async (range) => { leftPanel.loadRoomRange = async (range) => {
// pretend to load something // pretend to load something