diff --git a/src/domain/session/rightpanel/MemberListViewModel.js b/src/domain/session/rightpanel/MemberListViewModel.js index b75a3d1c..1633936a 100644 --- a/src/domain/session/rightpanel/MemberListViewModel.js +++ b/src/domain/session/rightpanel/MemberListViewModel.js @@ -47,7 +47,7 @@ export class MemberListViewModel extends ViewModel { this.nameDisambiguator.disambiguate(vm); return vm; } - const updater = (vm, params, newMember) => { + const updater = (params, vm, newMember) => { vm.updateFrom(newMember); this.nameDisambiguator.disambiguate(vm); }; diff --git a/src/observable/map/BaseObservableMap.ts b/src/observable/map/BaseObservableMap.ts index c4f7daae..b2f63c03 100644 --- a/src/observable/map/BaseObservableMap.ts +++ b/src/observable/map/BaseObservableMap.ts @@ -29,7 +29,7 @@ export interface IMapObserver<K, V> { export type BaseObservableMapConfig<K, V> = { join(_this: BaseObservableMap<K, V>, ...otherMaps: Array<BaseObservableMap<K, V>>): JoinedMap<K, V>; - mapValues(_this: BaseObservableMap<K, V>, mapper: any, updater?: (params: any) => void): MappedMap; + mapValues(_this: BaseObservableMap<K, V>, mapper: any, updater?: (params: any) => void): MappedMap<K, V>; sortValues(_this: BaseObservableMap<K, V>, comparator?: (a: any, b: any) => number): SortedMapList; filterValues(_this: BaseObservableMap<K, V>, filter: (v: V, k: K) => boolean): FilteredMap<K, V>; } @@ -67,7 +67,7 @@ export abstract class BaseObservableMap<K, V> extends BaseObservable<IMapObserve // to easily use the default implementation in a class that extends // this one (which is most likely what you want to do). abstract join(...otherMaps: Array<typeof this>): JoinedMap<K, V>; - abstract mapValues(mapper: any, updater?: (params: any) => void): MappedMap; + abstract mapValues(mapper: any, updater?: (params: any) => void): MappedMap<K, V>; abstract sortValues(comparator?: (a: any, b: any) => number): SortedMapList; abstract filterValues(filter: (v: V, k: K) => boolean): FilteredMap<K, V>; diff --git a/src/observable/map/FilteredMap.ts b/src/observable/map/FilteredMap.ts index c4810d9b..a9603d6d 100644 --- a/src/observable/map/FilteredMap.ts +++ b/src/observable/map/FilteredMap.ts @@ -39,7 +39,7 @@ export class FilteredMap<K, V> extends BaseObservableMap<K, V> { return this._config.join(this, ...otherMaps); } - mapValues(mapper: any, updater?: (params: any) => void): MappedMap{ + mapValues(mapper: any, updater?: (params: any) => void): MappedMap<K, V>{ return this._config.mapValues(this, mapper, updater); } diff --git a/src/observable/map/JoinedMap.ts b/src/observable/map/JoinedMap.ts index 6f285fd9..fbf2f39d 100644 --- a/src/observable/map/JoinedMap.ts +++ b/src/observable/map/JoinedMap.ts @@ -24,7 +24,7 @@ import {SubscriptionHandle} from "../BaseObservable" export class JoinedMap<K, V> extends BaseObservableMap<K, V> { protected _sources: BaseObservableMap<K, V>[]; - private _config: BaseObservableMapConfig<K, V> + private _config: BaseObservableMapConfig<K, V>; private _subscriptions?: SourceSubscriptionHandler<K, V>[]; constructor(sources: BaseObservableMap<K, V>[]) { @@ -37,7 +37,7 @@ export class JoinedMap<K, V> extends BaseObservableMap<K, V> { return this._config.join(this, ...otherMaps); } - mapValues(mapper: any, updater?: (params: any) => void): MappedMap{ + mapValues(mapper: any, updater?: (params: any) => void): MappedMap<K, V> { return this._config.mapValues(this, mapper, updater); } diff --git a/src/observable/map/LogMap.ts b/src/observable/map/LogMap.ts index 988aa71b..a287014a 100644 --- a/src/observable/map/LogMap.ts +++ b/src/observable/map/LogMap.ts @@ -42,7 +42,7 @@ export class LogMap<K, V> extends BaseObservableMap<K, V> { return this._config.join(this, ...otherMaps); } - mapValues(mapper: any, updater?: (params: any) => void): MappedMap { + mapValues(mapper: any, updater?: (params: any) => void): MappedMap<K, V> { return this._config.mapValues(this, mapper, updater); } diff --git a/src/observable/map/MappedMap.js b/src/observable/map/MappedMap.ts similarity index 57% rename from src/observable/map/MappedMap.js rename to src/observable/map/MappedMap.ts index a6b65c41..ff522621 100644 --- a/src/observable/map/MappedMap.js +++ b/src/observable/map/MappedMap.ts @@ -14,49 +14,83 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {BaseObservableMap} from "./BaseObservableMap"; +import {BaseObservableMap, BaseObservableMapConfig} from "./BaseObservableMap"; +import {config} from "./config"; +import {JoinedMap} from "./JoinedMap.js"; +import {FilteredMap} from "./FilteredMap.js"; +import {SortedMapList} from "../list/SortedMapList.js"; +import {SubscriptionHandle} from "../BaseObservable"; + /* so a mapped value can emit updates on it's own with this._emitSpontaneousUpdate that is passed in the mapping function how should the mapped value be notified of an update though? and can it then decide to not propagate the update? */ -export class MappedMap extends BaseObservableMap { - constructor(source, mapper, updater) { +export class MappedMap<K, V> extends BaseObservableMap<K, V> { + private _source: BaseObservableMap<K, V>; + private _mapper: Mapper<V>; + private _updater?: Updater<V>; + private _mappedValues: Map<K, V>; + private _subscription?: SubscriptionHandle; + private _config: BaseObservableMapConfig<K, V> + + constructor( + source: BaseObservableMap<K, V>, + mapper: Mapper<V>, + updater?: Updater<V> + ) { super(); this._source = source; this._mapper = mapper; this._updater = updater; - this._mappedValues = new Map(); + this._mappedValues = new Map<K, V>(); + this._config = config<K, V>(); } - _emitSpontaneousUpdate(key, params) { + join(...otherMaps: Array<typeof this>): JoinedMap<K, V> { + return this._config.join(this, ...otherMaps); + } + + mapValues(mapper: any, updater?: (params: any) => void): MappedMap<K, V>{ + return this._config.mapValues(this, mapper, updater); + } + + sortValues(comparator?: (a: any, b: any) => number): SortedMapList { + return this._config.sortValues(this, comparator); + } + + filterValues(filter: (v: V, k: K) => boolean): FilteredMap<K, V> { + return this._config.filterValues(this, filter); + } + + _emitSpontaneousUpdate(key: K, params: any) { const value = this._mappedValues.get(key); if (value) { this.emitUpdate(key, value, params); } } - onAdd(key, value) { + onAdd(key: K, value: V) { const emitSpontaneousUpdate = this._emitSpontaneousUpdate.bind(this, key); const mappedValue = this._mapper(value, emitSpontaneousUpdate); this._mappedValues.set(key, mappedValue); this.emitAdd(key, mappedValue); } - onRemove(key/*, _value*/) { + onRemove(key: K/*, _value*/) { const mappedValue = this._mappedValues.get(key); if (this._mappedValues.delete(key)) { - this.emitRemove(key, mappedValue); + if (mappedValue) this.emitRemove(key, mappedValue); } } - onUpdate(key, value, params) { + onUpdate(key: K, value: V, params: any) { // if an update is emitted while calling source.subscribe() from onSubscribeFirst, ignore it if (!this._mappedValues) { return; } const mappedValue = this._mappedValues.get(key); if (mappedValue !== undefined) { - this._updater?.(mappedValue, params, value); + this._updater?.(params, mappedValue, value); // TODO: map params somehow if needed? this.emitUpdate(key, mappedValue, params); } @@ -74,7 +108,7 @@ export class MappedMap extends BaseObservableMap { onUnsubscribeLast() { super.onUnsubscribeLast(); - this._subscription = this._subscription(); + if (this._subscription) this._subscription = this._subscription(); this._mappedValues.clear(); } @@ -91,7 +125,14 @@ export class MappedMap extends BaseObservableMap { return this._mappedValues.size; } - get(key) { + get(key: K): V | undefined { return this._mappedValues.get(key); } } + +type Mapper<V> = ( + value: V, + emitSpontaneousUpdate: any, +) => V; + +type Updater<V> = (params: any, mappedValue?: V, value?: V) => void; \ No newline at end of file diff --git a/src/observable/map/ObservableMap.ts b/src/observable/map/ObservableMap.ts index 7ee3d666..06776927 100644 --- a/src/observable/map/ObservableMap.ts +++ b/src/observable/map/ObservableMap.ts @@ -36,7 +36,7 @@ export class ObservableMap<K, V> extends BaseObservableMap<K, V> { return this._config.join(this, ...otherMaps); } - mapValues(mapper: any, updater?: (params: any) => void): MappedMap{ + mapValues(mapper: any, updater?: (params: any) => void): MappedMap<K, V> { return this._config.mapValues(this, mapper, updater); } diff --git a/src/observable/map/config.ts b/src/observable/map/config.ts index a0a63014..c91cfe1a 100644 --- a/src/observable/map/config.ts +++ b/src/observable/map/config.ts @@ -30,7 +30,7 @@ export function config<K, V>(): BaseObservableMapConfig<K, V> { join: (_this: BaseObservableMap<K, V>, ...otherMaps: Array<BaseObservableMap<K, V>>): JoinedMap<K, V> => { return new JoinedMap([_this].concat(otherMaps)); }, - mapValues: (_this: BaseObservableMap<K, V>, mapper: any, updater?: (params: any) => void): MappedMap => { + mapValues: (_this: BaseObservableMap<K, V>, mapper: any, updater: (params: any) => void): MappedMap<K, V> => { return new MappedMap(_this, mapper, updater); }, sortValues: (_this: BaseObservableMap<K, V>, comparator?: (a: any, b: any) => number): SortedMapList => {