From 6d7c983e8e8f7d33f1a704fe82b5a30972431cf8 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 9 Mar 2022 11:28:19 +0100 Subject: [PATCH 1/4] convert (Base)ObservableMap to typescript --- .../room/timeline/ReactionsViewModel.js | 2 +- src/matrix/room/members/MemberList.js | 2 +- src/observable/index.js | 4 +-- src/observable/list/SortedMapList.js | 2 +- src/observable/map/ApplyMap.js | 2 +- ...eObservableMap.js => BaseObservableMap.ts} | 30 +++++++++---------- src/observable/map/FilteredMap.js | 4 +-- src/observable/map/JoinedMap.js | 4 +-- src/observable/map/LogMap.js | 2 +- src/observable/map/MappedMap.js | 2 +- .../{ObservableMap.js => ObservableMap.ts} | 30 ++++++++++--------- 11 files changed, 42 insertions(+), 42 deletions(-) rename src/observable/map/{BaseObservableMap.js => BaseObservableMap.ts} (69%) rename src/observable/map/{ObservableMap.js => ObservableMap.ts} (90%) diff --git a/src/domain/session/room/timeline/ReactionsViewModel.js b/src/domain/session/room/timeline/ReactionsViewModel.js index fa48bec0..4f366af0 100644 --- a/src/domain/session/room/timeline/ReactionsViewModel.js +++ b/src/domain/session/room/timeline/ReactionsViewModel.js @@ -13,7 +13,7 @@ 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 {ObservableMap} from "../../../../observable/map/ObservableMap.js"; +import {ObservableMap} from "../../../../observable/map/ObservableMap"; export class ReactionsViewModel { constructor(parentTile) { diff --git a/src/matrix/room/members/MemberList.js b/src/matrix/room/members/MemberList.js index 9923fb87..f32a63d3 100644 --- a/src/matrix/room/members/MemberList.js +++ b/src/matrix/room/members/MemberList.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {ObservableMap} from "../../../observable/map/ObservableMap.js"; +import {ObservableMap} from "../../../observable/map/ObservableMap"; import {RetainedValue} from "../../../utils/RetainedValue"; export class MemberList extends RetainedValue { diff --git a/src/observable/index.js b/src/observable/index.js index 4d7f18a3..6057174b 100644 --- a/src/observable/index.js +++ b/src/observable/index.js @@ -18,14 +18,14 @@ import {SortedMapList} from "./list/SortedMapList.js"; import {FilteredMap} from "./map/FilteredMap.js"; import {MappedMap} from "./map/MappedMap.js"; import {JoinedMap} from "./map/JoinedMap.js"; -import {BaseObservableMap} from "./map/BaseObservableMap.js"; +import {BaseObservableMap} from "./map/BaseObservableMap"; // re-export "root" (of chain) collections export { ObservableArray } from "./list/ObservableArray"; export { SortedArray } from "./list/SortedArray"; export { MappedList } from "./list/MappedList"; export { AsyncMappedList } from "./list/AsyncMappedList"; export { ConcatList } from "./list/ConcatList"; -export { ObservableMap } from "./map/ObservableMap.js"; +export { ObservableMap } from "./map/ObservableMap"; // avoid circular dependency between these classes // and BaseObservableMap (as they extend it) diff --git a/src/observable/list/SortedMapList.js b/src/observable/list/SortedMapList.js index 38900380..d74dbade 100644 --- a/src/observable/list/SortedMapList.js +++ b/src/observable/list/SortedMapList.js @@ -133,7 +133,7 @@ export class SortedMapList extends BaseObservableList { } } -import {ObservableMap} from "../map/ObservableMap.js"; +import {ObservableMap} from "../map/ObservableMap"; export function tests() { return { diff --git a/src/observable/map/ApplyMap.js b/src/observable/map/ApplyMap.js index ad345595..6be7278a 100644 --- a/src/observable/map/ApplyMap.js +++ b/src/observable/map/ApplyMap.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {BaseObservableMap} from "./BaseObservableMap.js"; +import {BaseObservableMap} from "./BaseObservableMap"; export class ApplyMap extends BaseObservableMap { constructor(source, apply) { diff --git a/src/observable/map/BaseObservableMap.js b/src/observable/map/BaseObservableMap.ts similarity index 69% rename from src/observable/map/BaseObservableMap.js rename to src/observable/map/BaseObservableMap.ts index d3193931..694c017e 100644 --- a/src/observable/map/BaseObservableMap.js +++ b/src/observable/map/BaseObservableMap.ts @@ -16,7 +16,14 @@ limitations under the License. import {BaseObservable} from "../BaseObservable"; -export class BaseObservableMap extends BaseObservable { +export interface IMapObserver { + onReset(): void; + onAdd(key: K, value:V): void; + onUpdate(key: K, value: V, params: any): void; + onRemove(key: K, value: V): void +} + +export abstract class BaseObservableMap extends BaseObservable> { emitReset() { for(let h of this._handlers) { h.onReset(); @@ -24,15 +31,15 @@ export class BaseObservableMap extends BaseObservable { } // we need batch events, mostly on index based collection though? // maybe we should get started without? - emitAdd(key, value) { + emitAdd(key: K, value: V) { for(let h of this._handlers) { h.onAdd(key, value); } } - emitUpdate(key, value, ...params) { + emitUpdate(key, value, params) { for(let h of this._handlers) { - h.onUpdate(key, value, ...params); + h.onUpdate(key, value, params); } } @@ -42,16 +49,7 @@ export class BaseObservableMap extends BaseObservable { } } - [Symbol.iterator]() { - throw new Error("unimplemented"); - } - - get size() { - throw new Error("unimplemented"); - } - - // eslint-disable-next-line no-unused-vars - get(key) { - throw new Error("unimplemented"); - } + abstract [Symbol.iterator](): Iterator<[K, V]>; + abstract get size(): number; + abstract get(key: K): V | undefined; } diff --git a/src/observable/map/FilteredMap.js b/src/observable/map/FilteredMap.js index f7090502..d7e11fbe 100644 --- a/src/observable/map/FilteredMap.js +++ b/src/observable/map/FilteredMap.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {BaseObservableMap} from "./BaseObservableMap.js"; +import {BaseObservableMap} from "./BaseObservableMap"; export class FilteredMap extends BaseObservableMap { constructor(source, filter) { @@ -166,7 +166,7 @@ class FilterIterator { } } -import {ObservableMap} from "./ObservableMap.js"; +import {ObservableMap} from "./ObservableMap"; export function tests() { return { "filter preloaded list": assert => { diff --git a/src/observable/map/JoinedMap.js b/src/observable/map/JoinedMap.js index 7db04be1..d97c5677 100644 --- a/src/observable/map/JoinedMap.js +++ b/src/observable/map/JoinedMap.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {BaseObservableMap} from "./BaseObservableMap.js"; +import {BaseObservableMap} from "./BaseObservableMap"; export class JoinedMap extends BaseObservableMap { constructor(sources) { @@ -191,7 +191,7 @@ class SourceSubscriptionHandler { } -import { ObservableMap } from "./ObservableMap.js"; +import { ObservableMap } from "./ObservableMap"; export function tests() { diff --git a/src/observable/map/LogMap.js b/src/observable/map/LogMap.js index 4b8bb686..1beb4846 100644 --- a/src/observable/map/LogMap.js +++ b/src/observable/map/LogMap.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {BaseObservableMap} from "./BaseObservableMap.js"; +import {BaseObservableMap} from "./BaseObservableMap"; export class LogMap extends BaseObservableMap { constructor(source, log) { diff --git a/src/observable/map/MappedMap.js b/src/observable/map/MappedMap.js index 2a810058..a6b65c41 100644 --- a/src/observable/map/MappedMap.js +++ b/src/observable/map/MappedMap.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {BaseObservableMap} from "./BaseObservableMap.js"; +import {BaseObservableMap} from "./BaseObservableMap"; /* 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? diff --git a/src/observable/map/ObservableMap.js b/src/observable/map/ObservableMap.ts similarity index 90% rename from src/observable/map/ObservableMap.js rename to src/observable/map/ObservableMap.ts index 8f5a0922..0f681879 100644 --- a/src/observable/map/ObservableMap.js +++ b/src/observable/map/ObservableMap.ts @@ -14,15 +14,17 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {BaseObservableMap} from "./BaseObservableMap.js"; +import {BaseObservableMap} from "./BaseObservableMap"; -export class ObservableMap extends BaseObservableMap { - constructor(initialValues) { +export class ObservableMap extends BaseObservableMap { + private readonly _values: Map; + + constructor(initialValues: Iterable<[K, V]>) { super(); this._values = new Map(initialValues); } - update(key, params) { + update(key: K, params: any): boolean { const value = this._values.get(key); if (value !== undefined) { // could be the same value, so it's already updated @@ -34,7 +36,7 @@ export class ObservableMap extends BaseObservableMap { return false; // or return existing value? } - add(key, value) { + add(key: K, value: V): boolean { if (!this._values.has(key)) { this._values.set(key, value); this.emitAdd(key, value); @@ -43,7 +45,7 @@ export class ObservableMap extends BaseObservableMap { return false; // or return existing value? } - remove(key) { + remove(key: K): boolean { const value = this._values.get(key); if (value !== undefined) { this._values.delete(key); @@ -54,39 +56,39 @@ export class ObservableMap extends BaseObservableMap { } } - set(key, value) { + set(key: K, value: V): boolean { if (this._values.has(key)) { // We set the value here because update only supports inline updates this._values.set(key, value); - return this.update(key); + return this.update(key, undefined); } else { return this.add(key, value); } } - reset() { + reset(): void { this._values.clear(); this.emitReset(); } - get(key) { + get(key: K): V | undefined { return this._values.get(key); } - get size() { + get size(): number { return this._values.size; } - [Symbol.iterator]() { + [Symbol.iterator](): Iterator<[K, V]> { return this._values.entries(); } - values() { + values(): Iterator { return this._values.values(); } - keys() { + keys(): Iterator { return this._values.keys(); } } From 21080d2110849531087500328b558b02b5f941b1 Mon Sep 17 00:00:00 2001 From: Bruno Windels <274386+bwindels@users.noreply.github.com> Date: Wed, 9 Mar 2022 11:41:26 +0100 Subject: [PATCH 2/4] fix tests --- src/observable/map/ObservableMap.ts | 44 +++++++++++++++++++---------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/src/observable/map/ObservableMap.ts b/src/observable/map/ObservableMap.ts index 0f681879..719ce4b7 100644 --- a/src/observable/map/ObservableMap.ts +++ b/src/observable/map/ObservableMap.ts @@ -19,12 +19,12 @@ import {BaseObservableMap} from "./BaseObservableMap"; export class ObservableMap extends BaseObservableMap { private readonly _values: Map; - constructor(initialValues: Iterable<[K, V]>) { + constructor(initialValues?: Iterable<[K, V]>) { super(); this._values = new Map(initialValues); } - update(key: K, params: any): boolean { + update(key: K, params?: any): boolean { const value = this._values.get(key); if (value !== undefined) { // could be the same value, so it's already updated @@ -107,13 +107,16 @@ export function tests() { test_add(assert) { let fired = 0; - const map = new ObservableMap(); + const map = new ObservableMap(); map.subscribe({ onAdd(key, value) { fired += 1; assert.equal(key, 1); assert.deepEqual(value, {value: 5}); - } + }, + onUpdate() {}, + onRemove() {}, + onReset() {} }); map.add(1, {value: 5}); assert.equal(map.size, 1); @@ -122,7 +125,7 @@ export function tests() { test_update(assert) { let fired = 0; - const map = new ObservableMap(); + const map = new ObservableMap(); const value = {number: 5}; map.add(1, value); map.subscribe({ @@ -131,7 +134,10 @@ export function tests() { assert.equal(key, 1); assert.deepEqual(value, {number: 6}); assert.equal(params, "test"); - } + }, + onAdd() {}, + onRemove() {}, + onReset() {} }); value.number = 6; map.update(1, "test"); @@ -140,9 +146,12 @@ export function tests() { test_update_unknown(assert) { let fired = 0; - const map = new ObservableMap(); + const map = new ObservableMap(); map.subscribe({ - onUpdate() { fired += 1; } + onUpdate() { fired += 1; }, + onAdd() {}, + onRemove() {}, + onReset() {} }); const result = map.update(1); assert.equal(fired, 0); @@ -151,7 +160,7 @@ export function tests() { test_set(assert) { let add_fired = 0, update_fired = 0; - const map = new ObservableMap(); + const map = new ObservableMap(); map.subscribe({ onAdd(key, value) { add_fired += 1; @@ -162,7 +171,9 @@ export function tests() { update_fired += 1; assert.equal(key, 1); assert.deepEqual(value, {value: 7}); - } + }, + onRemove() {}, + onReset() {} }); // Add map.set(1, {value: 5}); @@ -176,7 +187,7 @@ export function tests() { test_remove(assert) { let fired = 0; - const map = new ObservableMap(); + const map = new ObservableMap(); const value = {value: 5}; map.add(1, value); map.subscribe({ @@ -184,7 +195,10 @@ export function tests() { fired += 1; assert.equal(key, 1); assert.deepEqual(value, {value: 5}); - } + }, + onAdd() {}, + onUpdate() {}, + onReset() {} }); map.remove(1); assert.equal(map.size, 0); @@ -192,8 +206,8 @@ export function tests() { }, test_iterate(assert) { - const results = []; - const map = new ObservableMap(); + const results: any[] = []; + const map = new ObservableMap(); map.add(1, {number: 5}); map.add(2, {number: 6}); map.add(3, {number: 7}); @@ -206,7 +220,7 @@ export function tests() { assert.equal(results.find(([key]) => key === 3)[1].number, 7); }, test_size(assert) { - const map = new ObservableMap(); + const map = new ObservableMap(); map.add(1, {number: 5}); map.add(2, {number: 6}); assert.equal(map.size, 2); From 762925d4a591b58235fa3846d3022daa75071898 Mon Sep 17 00:00:00 2001 From: Bruno Windels <274386+bwindels@users.noreply.github.com> Date: Wed, 9 Mar 2022 11:44:49 +0100 Subject: [PATCH 3/4] fix type error --- src/observable/map/ObservableMap.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/observable/map/ObservableMap.ts b/src/observable/map/ObservableMap.ts index 719ce4b7..8ada1843 100644 --- a/src/observable/map/ObservableMap.ts +++ b/src/observable/map/ObservableMap.ts @@ -19,7 +19,7 @@ import {BaseObservableMap} from "./BaseObservableMap"; export class ObservableMap extends BaseObservableMap { private readonly _values: Map; - constructor(initialValues?: Iterable<[K, V]>) { + constructor(initialValues?: Iterable) { super(); this._values = new Map(initialValues); } From 6150e91c3f82ab7c772dd2eb9841fddddae32bd0 Mon Sep 17 00:00:00 2001 From: Bruno Windels <274386+bwindels@users.noreply.github.com> Date: Wed, 9 Mar 2022 11:51:11 +0100 Subject: [PATCH 4/4] fix type error again --- src/observable/map/ObservableMap.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/observable/map/ObservableMap.ts b/src/observable/map/ObservableMap.ts index 8ada1843..d604ab0a 100644 --- a/src/observable/map/ObservableMap.ts +++ b/src/observable/map/ObservableMap.ts @@ -19,7 +19,7 @@ import {BaseObservableMap} from "./BaseObservableMap"; export class ObservableMap extends BaseObservableMap { private readonly _values: Map; - constructor(initialValues?: Iterable) { + constructor(initialValues?: (readonly [K, V])[]) { super(); this._values = new Map(initialValues); }