wip mapper updates

This commit is contained in:
Kegan Dougal 2021-12-06 17:09:17 +00:00
parent fce1d95a7c
commit cc69fc099d
4 changed files with 66 additions and 19 deletions

View file

@ -43,7 +43,7 @@ export class LeftPanelViewModel extends ViewModel {
} }
_mapTileViewModels(list) { _mapTileViewModels(list) {
return new MappedList(list, (roomOrInvite, emitChange) => { const mapper = (roomOrInvite, emitChange) => {
let vm; let vm;
if (roomOrInvite === null) { if (roomOrInvite === null) {
vm = new PlaceholderRoomTileViewModel(this.childOptions({room: null, emitChange})); vm = new PlaceholderRoomTileViewModel(this.childOptions({room: null, emitChange}));
@ -64,7 +64,11 @@ export class LeftPanelViewModel extends ViewModel {
} }
} }
return vm; return vm;
}); };
const updater = (tileViewModel, noIdea, roomOrInvite) => {
return mapper(roomOrInvite);
}
return new MappedList(list, mapper, updater);
} }
_updateCurrentVM(vm) { _updateCurrentVM(vm) {

View file

@ -17,12 +17,14 @@ limitations under the License.
import * as assert from "assert"; import * as assert from "assert";
import { BaseObservableList } from "../observable/list/BaseObservableList"; import { BaseObservableList } from "../observable/list/BaseObservableList";
import { ObservableMap } from "../observable/map/ObservableMap.js"; import { ObservableMap } from "../observable/map/ObservableMap.js";
import { SubscriptionHandle } from "../observable/BaseObservable";
import { Room } from "./room/Room.js"; import { Room } from "./room/Room.js";
// subset of Sync3 functions used in this list; interfaced out for testing // subset of Sync3 functions used in this list; interfaced out for testing
interface ISync { interface ISync {
count(): number; count(): number;
roomAtIndex(i: number): string roomAtIndex(i: number): string
indexOfRoom(roomId: string): number
} }
/** /**
@ -31,6 +33,7 @@ interface ISync {
export class Sync3ObservableList extends BaseObservableList<Room | null> { export class Sync3ObservableList extends BaseObservableList<Room | null> {
sync: ISync; sync: ISync;
rooms: ObservableMap; rooms: ObservableMap;
subscription: SubscriptionHandle | null;
/** /**
* Construct an observable list that produces Rooms within the sliding window of Sync3 responses * Construct an observable list that produces Rooms within the sliding window of Sync3 responses
@ -41,9 +44,40 @@ export class Sync3ObservableList extends BaseObservableList<Room | null> {
constructor(sync3: ISync, rooms: ObservableMap) { constructor(sync3: ISync, rooms: ObservableMap) {
super(); super();
this.sync = sync3; this.sync = sync3;
this.subscription = null;
this.rooms = rooms; this.rooms = rooms;
} }
onSubscribeFirst() {
this.subscription = this.rooms.subscribe(this);
}
onUnsubscribeLast() {
if (!this.subscription) {
return;
}
this.subscription();
this.subscription = null;
}
onAdd(index, entry) {
let i = this.sync.indexOfRoom(entry.id);
this.emitUpdate(i, entry); // we always emit updates as we have num_joined_rooms entries (placeholders)
}
onUpdate(index, entry, params) {
let i = this.sync.indexOfRoom(entry.id);
if (i === -1) {
return;
}
this.emitUpdate(i, entry); // we always emit updates as we have num_joined_rooms entries (placeholders)
}
onRemove(index, entry) {
let i = this.sync.indexOfRoom(entry.id);
this.emitUpdate(i, entry); // we always emit updates as we have num_joined_rooms entries (placeholders)
}
get length(): number { get length(): number {
return this.sync.count(); return this.sync.count();
} }
@ -120,6 +154,15 @@ export function tests() {
roomAtIndex: (i: number): string => { roomAtIndex: (i: number): string => {
return indexToRoomId[i]; return indexToRoomId[i];
}, },
indexOfRoom(roomId: string): number {
for (let i of Object.keys(indexToRoomId)) {
let r = indexToRoomId[i];
if (r === roomId) {
return Number(i);
}
}
return -1;
}
}; };
makeRooms(100).forEach((r) => { makeRooms(100).forEach((r) => {

View file

@ -15,21 +15,21 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {BaseObservableList} from "./BaseObservableList"; import { BaseObservableList } from "./BaseObservableList";
import {findAndUpdateInArray} from "./common"; import { findAndUpdateInArray } from "./common";
export type Mapper<F,T> = (value: F) => T export type Mapper<F, T> = (value: F) => T
export type Updater<F,T> = (mappedValue: T, params: any, value: F) => void; export type Updater<F, T> = (mappedValue: T, params: any, value: F) => void;
export class BaseMappedList<F,T,R = T> extends BaseObservableList<T> { export class BaseMappedList<F, T, R = T> extends BaseObservableList<T> {
protected _sourceList: BaseObservableList<F>; protected _sourceList: BaseObservableList<F>;
protected _sourceUnsubscribe: (() => void) | null = null; protected _sourceUnsubscribe: (() => void) | null = null;
_mapper: Mapper<F,R>; _mapper: Mapper<F, R>;
_updater?: Updater<F,T>; _updater?: Updater<F, T>;
_removeCallback?: (value: T) => void; _removeCallback?: (value: T) => void;
_mappedValues: T[] | null = null; _mappedValues: T[] | null = null;
constructor(sourceList: BaseObservableList<F>, mapper: Mapper<F,R>, updater?: Updater<F,T>, removeCallback?: (value: T) => void) { constructor(sourceList: BaseObservableList<F>, mapper: Mapper<F, R>, updater?: Updater<F, T>, removeCallback?: (value: T) => void) {
super(); super();
this._sourceList = sourceList; this._sourceList = sourceList;
this._mapper = mapper; this._mapper = mapper;
@ -50,12 +50,12 @@ export class BaseMappedList<F,T,R = T> extends BaseObservableList<T> {
} }
} }
export function runAdd<F,T,R>(list: BaseMappedList<F,T,R>, index: number, mappedValue: T): void { export function runAdd<F, T, R>(list: BaseMappedList<F, T, R>, index: number, mappedValue: T): void {
list._mappedValues!.splice(index, 0, mappedValue); list._mappedValues!.splice(index, 0, mappedValue);
list.emitAdd(index, mappedValue); list.emitAdd(index, mappedValue);
} }
export function runUpdate<F,T,R>(list: BaseMappedList<F,T,R>, index: number, value: F, params: any): void { export function runUpdate<F, T, R>(list: BaseMappedList<F, T, R>, index: number, value: F, params: any): void {
const mappedValue = list._mappedValues![index]; const mappedValue = list._mappedValues![index];
if (list._updater) { if (list._updater) {
list._updater(mappedValue, params, value); list._updater(mappedValue, params, value);
@ -63,7 +63,7 @@ export function runUpdate<F,T,R>(list: BaseMappedList<F,T,R>, index: number, val
list.emitUpdate(index, mappedValue, params); list.emitUpdate(index, mappedValue, params);
} }
export function runRemove<F,T,R>(list: BaseMappedList<F,T,R>, index: number): void { export function runRemove<F, T, R>(list: BaseMappedList<F, T, R>, index: number): void {
const mappedValue = list._mappedValues![index]; const mappedValue = list._mappedValues![index];
list._mappedValues!.splice(index, 1); list._mappedValues!.splice(index, 1);
if (list._removeCallback) { if (list._removeCallback) {
@ -72,14 +72,14 @@ export function runRemove<F,T,R>(list: BaseMappedList<F,T,R>, index: number): vo
list.emitRemove(index, mappedValue); list.emitRemove(index, mappedValue);
} }
export function runMove<F,T,R>(list: BaseMappedList<F,T,R>, fromIdx: number, toIdx: number): void { export function runMove<F, T, R>(list: BaseMappedList<F, T, R>, fromIdx: number, toIdx: number): void {
const mappedValue = list._mappedValues![fromIdx]; const mappedValue = list._mappedValues![fromIdx];
list._mappedValues!.splice(fromIdx, 1); list._mappedValues!.splice(fromIdx, 1);
list._mappedValues!.splice(toIdx, 0, mappedValue); list._mappedValues!.splice(toIdx, 0, mappedValue);
list.emitMove(fromIdx, toIdx, mappedValue); list.emitMove(fromIdx, toIdx, mappedValue);
} }
export function runReset<F,T,R>(list: BaseMappedList<F,T,R>): void { export function runReset<F, T, R>(list: BaseMappedList<F, T, R>): void {
list._mappedValues = []; list._mappedValues = [];
list.emitReset(); list.emitReset();
} }

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {BaseObservableList, IListObserver} from "./BaseObservableList"; import { BaseObservableList, IListObserver } from "./BaseObservableList";
export class ConcatList<T> extends BaseObservableList<T> implements IListObserver<T> { export class ConcatList<T> extends BaseObservableList<T> implements IListObserver<T> {
protected _sourceLists: BaseObservableList<T>[]; protected _sourceLists: BaseObservableList<T>[];
@ -50,7 +50,7 @@ export class ConcatList<T> extends BaseObservableList<T> implements IListObserve
// reset, and // reset, and
this.emitReset(); this.emitReset();
let idx = 0; let idx = 0;
for(const item of this) { for (const item of this) {
this.emitAdd(idx, item); this.emitAdd(idx, item);
idx += 1; idx += 1;
} }
@ -106,8 +106,8 @@ export class ConcatList<T> extends BaseObservableList<T> implements IListObserve
} }
} }
import {ObservableArray} from "./ObservableArray"; import { ObservableArray } from "./ObservableArray";
import {defaultObserverWith} from "./BaseObservableList"; import { defaultObserverWith } from "./BaseObservableList";
export async function tests() { export async function tests() {
return { return {
test_length(assert) { test_length(assert) {