diff --git a/src/domain/navigation/Navigation.js b/src/domain/navigation/Navigation.js index 3167475f..340ae0d5 100644 --- a/src/domain/navigation/Navigation.js +++ b/src/domain/navigation/Navigation.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {BaseObservableValue, ObservableValue} from "../../observable/ObservableValue.js"; +import {BaseObservableValue, ObservableValue} from "../../observable/ObservableValue"; export class Navigation { constructor(allowsChild) { diff --git a/src/domain/session/RoomGridViewModel.js b/src/domain/session/RoomGridViewModel.js index 08887f3e..d89d821a 100644 --- a/src/domain/session/RoomGridViewModel.js +++ b/src/domain/session/RoomGridViewModel.js @@ -186,7 +186,7 @@ export class RoomGridViewModel extends ViewModel { } import {createNavigation} from "../navigation/index.js"; -import {ObservableValue} from "../../observable/ObservableValue.js"; +import {ObservableValue} from "../../observable/ObservableValue"; export function tests() { class RoomVMMock { diff --git a/src/domain/session/RoomViewModelObservable.js b/src/domain/session/RoomViewModelObservable.js index b9549905..2a706045 100644 --- a/src/domain/session/RoomViewModelObservable.js +++ b/src/domain/session/RoomViewModelObservable.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {ObservableValue} from "../../observable/ObservableValue.js"; +import {ObservableValue} from "../../observable/ObservableValue"; /** Depending on the status of a room (invited, joined, archived, or none), @@ -77,4 +77,4 @@ export class RoomViewModelObservable extends ObservableValue { this.unsubscribeAll(); this.get()?.dispose(); } -} \ No newline at end of file +} diff --git a/src/domain/session/room/timeline/ReactionsViewModel.js b/src/domain/session/room/timeline/ReactionsViewModel.js index ca5d43f0..25d74b49 100644 --- a/src/domain/session/room/timeline/ReactionsViewModel.js +++ b/src/domain/session/room/timeline/ReactionsViewModel.js @@ -189,7 +189,7 @@ import {HomeServer as MockHomeServer} from "../../../../mocks/HomeServer.js"; // other imports import {BaseMessageTile} from "./tiles/BaseMessageTile.js"; import {MappedList} from "../../../../observable/list/MappedList.js"; -import {ObservableValue} from "../../../../observable/ObservableValue.js"; +import {ObservableValue} from "../../../../observable/ObservableValue"; import {PowerLevels} from "../../../../matrix/room/PowerLevels.js"; export function tests() { diff --git a/src/domain/session/room/timeline/TilesCollection.js b/src/domain/session/room/timeline/TilesCollection.js index 497c0b0d..b3696fad 100644 --- a/src/domain/session/room/timeline/TilesCollection.js +++ b/src/domain/session/room/timeline/TilesCollection.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {BaseObservableList} from "../../../../observable/list/BaseObservableList.js"; +import {BaseObservableList} from "../../../../observable/list/BaseObservableList"; import {sortedIndex} from "../../../../utils/sortedIndex.js"; // maps 1..n entries to 0..1 tile. Entries are what is stored in the timeline, either an event or fragmentboundary diff --git a/src/matrix/Session.js b/src/matrix/Session.js index 87a3150c..36c8e084 100644 --- a/src/matrix/Session.js +++ b/src/matrix/Session.js @@ -40,7 +40,7 @@ import { writeKey as ssssWriteKey, } from "./ssss/index.js"; import {SecretStorage} from "./ssss/SecretStorage.js"; -import {ObservableValue, RetainedObservableValue} from "../observable/ObservableValue.js"; +import {ObservableValue, RetainedObservableValue} from "../observable/ObservableValue"; const PICKLE_KEY = "DEFAULT_KEY"; const PUSHER_KEY = "pusher"; diff --git a/src/matrix/SessionContainer.js b/src/matrix/SessionContainer.js index 479bb7a8..899b07ed 100644 --- a/src/matrix/SessionContainer.js +++ b/src/matrix/SessionContainer.js @@ -18,7 +18,7 @@ limitations under the License. import {createEnum} from "../utils/enum.js"; import {lookupHomeserver} from "./well-known.js"; import {AbortableOperation} from "../utils/AbortableOperation"; -import {ObservableValue} from "../observable/ObservableValue.js"; +import {ObservableValue} from "../observable/ObservableValue"; import {HomeServerApi} from "./net/HomeServerApi.js"; import {Reconnector, ConnectionStatus} from "./net/Reconnector.js"; import {ExponentialRetryDelay} from "./net/ExponentialRetryDelay.js"; diff --git a/src/matrix/Sync.js b/src/matrix/Sync.js index bcd29ab4..e010f90d 100644 --- a/src/matrix/Sync.js +++ b/src/matrix/Sync.js @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {ObservableValue} from "../observable/ObservableValue.js"; +import {ObservableValue} from "../observable/ObservableValue"; import {createEnum} from "../utils/enum.js"; const INCREMENTAL_TIMEOUT = 30000; diff --git a/src/matrix/net/Reconnector.js b/src/matrix/net/Reconnector.js index d3cf790f..6fd2ca94 100644 --- a/src/matrix/net/Reconnector.js +++ b/src/matrix/net/Reconnector.js @@ -15,7 +15,7 @@ limitations under the License. */ import {createEnum} from "../../utils/enum.js"; -import {ObservableValue} from "../../observable/ObservableValue.js"; +import {ObservableValue} from "../../observable/ObservableValue"; export const ConnectionStatus = createEnum( "Waiting", diff --git a/src/matrix/room/BaseRoom.js b/src/matrix/room/BaseRoom.js index aac962ac..43b2cf51 100644 --- a/src/matrix/room/BaseRoom.js +++ b/src/matrix/room/BaseRoom.js @@ -29,7 +29,7 @@ import {ObservedEventMap} from "./ObservedEventMap.js"; import {DecryptionSource} from "../e2ee/common.js"; import {ensureLogItem} from "../../logging/utils.js"; import {PowerLevels} from "./PowerLevels.js"; -import {RetainedObservableValue} from "../../observable/ObservableValue.js"; +import {RetainedObservableValue} from "../../observable/ObservableValue"; const EVENT_ENCRYPTED_TYPE = "m.room.encrypted"; diff --git a/src/matrix/room/ObservedEventMap.js b/src/matrix/room/ObservedEventMap.js index 59f0e26a..6b20f85e 100644 --- a/src/matrix/room/ObservedEventMap.js +++ b/src/matrix/room/ObservedEventMap.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {BaseObservableValue} from "../../observable/ObservableValue.js"; +import {BaseObservableValue} from "../../observable/ObservableValue"; export class ObservedEventMap { constructor(notifyEmpty) { diff --git a/src/mocks/Clock.js b/src/mocks/Clock.js index 97b7462a..440c4cb4 100644 --- a/src/mocks/Clock.js +++ b/src/mocks/Clock.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {ObservableValue} from "../observable/ObservableValue.js"; +import {ObservableValue} from "../observable/ObservableValue"; class Timeout { constructor(elapsed, ms) { diff --git a/src/observable/BaseObservable.js b/src/observable/BaseObservable.ts similarity index 76% rename from src/observable/BaseObservable.js rename to src/observable/BaseObservable.ts index 0f9934c3..16bd3b81 100644 --- a/src/observable/BaseObservable.js +++ b/src/observable/BaseObservable.ts @@ -14,20 +14,18 @@ See the License for the specific language governing permissions and limitations under the License. */ -export class BaseObservable { - constructor() { - this._handlers = new Set(); - } +export abstract class BaseObservable { + protected _handlers: Set = new Set(); - onSubscribeFirst() { + onSubscribeFirst(): void { } - onUnsubscribeLast() { + onUnsubscribeLast(): void { } - subscribe(handler) { + subscribe(handler: T): () => void { this._handlers.add(handler); if (this._handlers.size === 1) { this.onSubscribeFirst(); @@ -37,7 +35,7 @@ export class BaseObservable { }; } - unsubscribe(handler) { + unsubscribe(handler: T | null): null { if (handler) { this._handlers.delete(handler); if (this._handlers.size === 0) { @@ -48,14 +46,14 @@ export class BaseObservable { return null; } - unsubscribeAll() { + unsubscribeAll(): void { if (this._handlers.size !== 0) { this._handlers.clear(); this.onUnsubscribeLast(); } } - get hasSubscriptions() { + get hasSubscriptions(): boolean { return this._handlers.size !== 0; } @@ -63,13 +61,11 @@ export class BaseObservable { } export function tests() { - class Collection extends BaseObservable { - constructor() { - super(); - this.firstSubscribeCalls = 0; - this.firstUnsubscribeCalls = 0; - } - onSubscribeFirst() { this.firstSubscribeCalls += 1; } + class Collection extends BaseObservable<{}> { + firstSubscribeCalls: number= 0; + firstUnsubscribeCalls: number = 0; + + onSubscribeFirst() { this.firstSubscribeCalls += 1; } onUnsubscribeLast() { this.firstUnsubscribeCalls += 1; } } diff --git a/src/observable/ObservableValue.js b/src/observable/ObservableValue.ts similarity index 74% rename from src/observable/ObservableValue.js rename to src/observable/ObservableValue.ts index 8a433444..02d5fc69 100644 --- a/src/observable/ObservableValue.js +++ b/src/observable/ObservableValue.ts @@ -15,21 +15,19 @@ limitations under the License. */ import {AbortError} from "../utils/error.js"; -import {BaseObservable} from "./BaseObservable.js"; +import {BaseObservable} from "./BaseObservable"; // like an EventEmitter, but doesn't have an event type -export class BaseObservableValue extends BaseObservable { - emit(argument) { +export abstract class BaseObservableValue extends BaseObservable<(value: T) => void> { + emit(argument: T) { for (const h of this._handlers) { h(argument); } } - get() { - throw new Error("unimplemented"); - } + abstract get(): T; - waitFor(predicate) { + waitFor(predicate: (value: T) => boolean): IWaitHandle { if (predicate(this.get())) { return new ResolvedWaitForHandle(Promise.resolve(this.get())); } else { @@ -38,8 +36,17 @@ export class BaseObservableValue extends BaseObservable { } } -class WaitForHandle { - constructor(observable, predicate) { +interface IWaitHandle { + promise: Promise; + dispose(): void; +} + +class WaitForHandle implements IWaitHandle { + private _promise: Promise + private _reject: ((reason?: any) => void) | null; + private _subscription: (() => void) | null; + + constructor(observable: BaseObservableValue, predicate: (value: T) => boolean) { this._promise = new Promise((resolve, reject) => { this._reject = reject; this._subscription = observable.subscribe(v => { @@ -52,7 +59,7 @@ class WaitForHandle { }); } - get promise() { + get promise(): Promise { return this._promise; } @@ -68,25 +75,24 @@ class WaitForHandle { } } -class ResolvedWaitForHandle { - constructor(promise) { - this.promise = promise; - } - +class ResolvedWaitForHandle implements IWaitHandle { + constructor(public promise: Promise) {} dispose() {} } -export class ObservableValue extends BaseObservableValue { - constructor(initialValue) { +export class ObservableValue extends BaseObservableValue { + private _value: T; + + constructor(initialValue: T) { super(); this._value = initialValue; } - get() { + get(): T { return this._value; } - set(value) { + set(value: T): void { if (value !== this._value) { this._value = value; this.emit(this._value); @@ -94,8 +100,10 @@ export class ObservableValue extends BaseObservableValue { } } -export class RetainedObservableValue extends ObservableValue { - constructor(initialValue, freeCallback) { +export class RetainedObservableValue extends ObservableValue { + private _freeCallback: () => void; + + constructor(initialValue: T, freeCallback: () => void) { super(initialValue); this._freeCallback = freeCallback; } @@ -109,7 +117,7 @@ export class RetainedObservableValue extends ObservableValue { export function tests() { return { "set emits an update": assert => { - const a = new ObservableValue(); + const a = new ObservableValue(0); let fired = false; const subscription = a.subscribe(v => { fired = true; @@ -140,7 +148,7 @@ export function tests() { assert.strictEqual(a.get(), 6); }, "waitFor promise rejects when disposed": async assert => { - const a = new ObservableValue(); + const a = new ObservableValue(0); const handle = a.waitFor(() => false); Promise.resolve().then(() => { handle.dispose(); diff --git a/src/observable/list/AsyncMappedList.js b/src/observable/list/AsyncMappedList.js index 604d8e94..9af1f95a 100644 --- a/src/observable/list/AsyncMappedList.js +++ b/src/observable/list/AsyncMappedList.js @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {BaseMappedList, runAdd, runUpdate, runRemove, runMove, runReset} from "./BaseMappedList.js"; +import {BaseMappedList, runAdd, runUpdate, runRemove, runMove, runReset} from "./BaseMappedList"; export class AsyncMappedList extends BaseMappedList { constructor(sourceList, mapper, updater, removeCallback) { diff --git a/src/observable/list/BaseMappedList.js b/src/observable/list/BaseMappedList.js deleted file mode 100644 index 1ccd4e12..00000000 --- a/src/observable/list/BaseMappedList.js +++ /dev/null @@ -1,77 +0,0 @@ -/* -Copyright 2020 Bruno Windels -Copyright 2021 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 {BaseObservableList} from "./BaseObservableList.js"; -import {findAndUpdateInArray} from "./common.js"; - -export class BaseMappedList extends BaseObservableList { - constructor(sourceList, mapper, updater, removeCallback) { - super(); - this._sourceList = sourceList; - this._mapper = mapper; - this._updater = updater; - this._removeCallback = removeCallback; - this._mappedValues = null; - this._sourceUnsubscribe = null; - } - - findAndUpdate(predicate, updater) { - return findAndUpdateInArray(predicate, this._mappedValues, this, updater); - } - - get length() { - return this._mappedValues.length; - } - - [Symbol.iterator]() { - return this._mappedValues.values(); - } -} - -export function runAdd(list, index, mappedValue) { - list._mappedValues.splice(index, 0, mappedValue); - list.emitAdd(index, mappedValue); -} - -export function runUpdate(list, index, value, params) { - const mappedValue = list._mappedValues[index]; - if (list._updater) { - list._updater(mappedValue, params, value); - } - list.emitUpdate(index, mappedValue, params); -} - -export function runRemove(list, index) { - const mappedValue = list._mappedValues[index]; - list._mappedValues.splice(index, 1); - if (list._removeCallback) { - list._removeCallback(mappedValue); - } - list.emitRemove(index, mappedValue); -} - -export function runMove(list, fromIdx, toIdx) { - const mappedValue = list._mappedValues[fromIdx]; - list._mappedValues.splice(fromIdx, 1); - list._mappedValues.splice(toIdx, 0, mappedValue); - list.emitMove(fromIdx, toIdx, mappedValue); -} - -export function runReset(list) { - list._mappedValues = []; - list.emitReset(); -} diff --git a/src/observable/list/BaseMappedList.ts b/src/observable/list/BaseMappedList.ts new file mode 100644 index 00000000..f339d113 --- /dev/null +++ b/src/observable/list/BaseMappedList.ts @@ -0,0 +1,85 @@ +/* +Copyright 2020 Bruno Windels +Copyright 2021 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 {BaseObservableList} from "./BaseObservableList"; +import {findAndUpdateInArray} from "./common"; + +export type Mapper = (value: F) => T +export type Updater = (mappedValue: T, params: any, value: F) => void; + +export class BaseMappedList extends BaseObservableList { + protected _sourceList: BaseObservableList; + protected _sourceUnsubscribe: (() => void) | null = null; + _mapper: Mapper; + _updater: Updater; + _removeCallback: ((value: T) => void) | null; + _mappedValues: T[] | null = null; + + constructor(sourceList: BaseObservableList, mapper: Mapper, updater: Updater, removeCallback: ((value: T) => void) | null = null) { + super(); + this._sourceList = sourceList; + this._mapper = mapper; + this._updater = updater; + this._removeCallback = removeCallback; + } + + findAndUpdate(predicate: (value: T) => boolean, updater: (value: T) => any | false) { + return findAndUpdateInArray(predicate, this._mappedValues!, this, updater); + } + + get length() { + return this._mappedValues!.length; + } + + [Symbol.iterator]() { + return this._mappedValues!.values(); + } +} + +export function runAdd(list: BaseMappedList, index: number, mappedValue: T): void { + list._mappedValues!.splice(index, 0, mappedValue); + list.emitAdd(index, mappedValue); +} + +export function runUpdate(list: BaseMappedList, index: number, value: F, params: any): void { + const mappedValue = list._mappedValues![index]; + if (list._updater) { + list._updater(mappedValue, params, value); + } + list.emitUpdate(index, mappedValue, params); +} + +export function runRemove(list: BaseMappedList, index: number): void { + const mappedValue = list._mappedValues![index]; + list._mappedValues!.splice(index, 1); + if (list._removeCallback) { + list._removeCallback(mappedValue); + } + list.emitRemove(index, mappedValue); +} + +export function runMove(list: BaseMappedList, fromIdx: number, toIdx: number): void { + const mappedValue = list._mappedValues![fromIdx]; + list._mappedValues!.splice(fromIdx, 1); + list._mappedValues!.splice(toIdx, 0, mappedValue); + list.emitMove(fromIdx, toIdx, mappedValue); +} + +export function runReset(list: BaseMappedList): void { + list._mappedValues = []; + list.emitReset(); +} diff --git a/src/observable/list/BaseObservableList.js b/src/observable/list/BaseObservableList.ts similarity index 60% rename from src/observable/list/BaseObservableList.js rename to src/observable/list/BaseObservableList.ts index b3757a13..9ba6559a 100644 --- a/src/observable/list/BaseObservableList.js +++ b/src/observable/list/BaseObservableList.ts @@ -14,9 +14,17 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {BaseObservable} from "../BaseObservable.js"; +import {BaseObservable} from "../BaseObservable"; -export class BaseObservableList extends BaseObservable { +export interface IListObserver { + onReset(list: BaseObservableList): void; + onAdd(index: number, value:T, list: BaseObservableList): void; + onUpdate(index: number, value: T, params: any, list: BaseObservableList): void; + onRemove(index: number, value: T, list: BaseObservableList): void + onMove(from: number, to: number, value: T, list: BaseObservableList): void +} + +export abstract class BaseObservableList extends BaseObservable> { emitReset() { for(let h of this._handlers) { h.onReset(this); @@ -24,19 +32,19 @@ export class BaseObservableList extends BaseObservable { } // we need batch events, mostly on index based collection though? // maybe we should get started without? - emitAdd(index, value) { + emitAdd(index: number, value: T): void { for(let h of this._handlers) { h.onAdd(index, value, this); } } - emitUpdate(index, value, params) { + emitUpdate(index: number, value: T, params: any): void { for(let h of this._handlers) { h.onUpdate(index, value, params, this); } } - emitRemove(index, value) { + emitRemove(index: number, value: T): void { for(let h of this._handlers) { h.onRemove(index, value, this); } @@ -44,17 +52,12 @@ export class BaseObservableList extends BaseObservable { // toIdx assumes the item has already // been removed from its fromIdx - emitMove(fromIdx, toIdx, value) { + emitMove(fromIdx: number, toIdx: number, value: T): void { for(let h of this._handlers) { h.onMove(fromIdx, toIdx, value, this); } } - [Symbol.iterator]() { - throw new Error("unimplemented"); - } - - get length() { - throw new Error("unimplemented"); - } + abstract [Symbol.iterator](): IterableIterator; + abstract get length(): number; } diff --git a/src/observable/list/ConcatList.js b/src/observable/list/ConcatList.js index d395e807..e87ccb60 100644 --- a/src/observable/list/ConcatList.js +++ b/src/observable/list/ConcatList.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {BaseObservableList} from "./BaseObservableList.js"; +import {BaseObservableList} from "./BaseObservableList"; export class ConcatList extends BaseObservableList { constructor(...sourceLists) { diff --git a/src/observable/list/MappedList.js b/src/observable/list/MappedList.js index 096a018f..c799fcff 100644 --- a/src/observable/list/MappedList.js +++ b/src/observable/list/MappedList.js @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {BaseMappedList, runAdd, runUpdate, runRemove, runMove, runReset} from "./BaseMappedList.js"; +import {BaseMappedList, runAdd, runUpdate, runRemove, runMove, runReset} from "./BaseMappedList"; export class MappedList extends BaseMappedList { onSubscribeFirst() { @@ -57,7 +57,7 @@ export class MappedList extends BaseMappedList { } import {ObservableArray} from "./ObservableArray.js"; -import {BaseObservableList} from "./BaseObservableList.js"; +import {BaseObservableList} from "./BaseObservableList"; export async function tests() { class MockList extends BaseObservableList { diff --git a/src/observable/list/ObservableArray.js b/src/observable/list/ObservableArray.js index 0f9ee99d..5d9f5c12 100644 --- a/src/observable/list/ObservableArray.js +++ b/src/observable/list/ObservableArray.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {BaseObservableList} from "./BaseObservableList.js"; +import {BaseObservableList} from "./BaseObservableList"; export class ObservableArray extends BaseObservableList { constructor(initialValues = []) { diff --git a/src/observable/list/SortedArray.js b/src/observable/list/SortedArray.js index 323cf776..874d1b04 100644 --- a/src/observable/list/SortedArray.js +++ b/src/observable/list/SortedArray.js @@ -14,9 +14,9 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {BaseObservableList} from "./BaseObservableList.js"; +import {BaseObservableList} from "./BaseObservableList"; import {sortedIndex} from "../../utils/sortedIndex.js"; -import {findAndUpdateInArray} from "./common.js"; +import {findAndUpdateInArray} from "./common"; export class SortedArray extends BaseObservableList { constructor(comparator) { diff --git a/src/observable/list/SortedMapList.js b/src/observable/list/SortedMapList.js index babf5c35..2421419e 100644 --- a/src/observable/list/SortedMapList.js +++ b/src/observable/list/SortedMapList.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {BaseObservableList} from "./BaseObservableList.js"; +import {BaseObservableList} from "./BaseObservableList"; import {sortedIndex} from "../../utils/sortedIndex.js"; /* diff --git a/src/observable/list/common.js b/src/observable/list/common.ts similarity index 83% rename from src/observable/list/common.js rename to src/observable/list/common.ts index 8dbf7873..c67a841b 100644 --- a/src/observable/list/common.js +++ b/src/observable/list/common.ts @@ -14,9 +14,10 @@ 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 {BaseObservableList} from "./BaseObservableList"; /* inline update of item in collection backed by array, without replacing the preexising item */ -export function findAndUpdateInArray(predicate, array, observable, updater) { +export function findAndUpdateInArray(predicate: (value: T) => boolean, array: T[], observable: BaseObservableList, updater: (value: T) => any | false) { const index = array.findIndex(predicate); if (index !== -1) { const value = array[index]; @@ -29,4 +30,4 @@ export function findAndUpdateInArray(predicate, array, observable, updater) { return true; } return false; -} \ No newline at end of file +} diff --git a/src/observable/map/BaseObservableMap.js b/src/observable/map/BaseObservableMap.js index 79df21f6..d3193931 100644 --- a/src/observable/map/BaseObservableMap.js +++ b/src/observable/map/BaseObservableMap.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {BaseObservable} from "../BaseObservable.js"; +import {BaseObservable} from "../BaseObservable"; export class BaseObservableMap extends BaseObservable { emitReset() { diff --git a/src/platform/web/dom/History.js b/src/platform/web/dom/History.js index 68e4ef78..d51974bb 100644 --- a/src/platform/web/dom/History.js +++ b/src/platform/web/dom/History.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {BaseObservableValue} from "../../../observable/ObservableValue.js"; +import {BaseObservableValue} from "../../../observable/ObservableValue"; export class History extends BaseObservableValue { handleEvent(event) { diff --git a/src/platform/web/dom/OnlineStatus.js b/src/platform/web/dom/OnlineStatus.js index 588c0815..48e4e912 100644 --- a/src/platform/web/dom/OnlineStatus.js +++ b/src/platform/web/dom/OnlineStatus.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {BaseObservableValue} from "../../../observable/ObservableValue.js"; +import {BaseObservableValue} from "../../../observable/ObservableValue"; export class OnlineStatus extends BaseObservableValue { constructor() { diff --git a/src/platform/web/ui/general/ListView.ts b/src/platform/web/ui/general/ListView.ts index cdfdbf76..e6d15755 100644 --- a/src/platform/web/ui/general/ListView.ts +++ b/src/platform/web/ui/general/ListView.ts @@ -16,7 +16,7 @@ limitations under the License. import {el} from "./html"; import {mountView, insertAt} from "./utils"; -import {BaseObservableList as ObservableList} from "../../../../observable/list/BaseObservableList.js"; +import {BaseObservableList as ObservableList} from "../../../../observable/list/BaseObservableList"; import {IView, IMountArgs} from "./types"; interface IOptions { @@ -27,7 +27,7 @@ interface IOptions { parentProvidesUpdates?: boolean } -type SubscriptionHandle = () => undefined; +type SubscriptionHandle = () => void; export class ListView implements IView { @@ -115,7 +115,8 @@ export class ListView implements IView { } private _unloadList() { - this._subscription = this._subscription!(); + this._subscription!() + this._subscription = undefined; for (let child of this._childInstances!) { child.unmount(); } @@ -137,26 +138,34 @@ export class ListView implements IView { this._root!.appendChild(fragment); } - protected onAdd(idx: number, value: T) { + onReset() { + for (const child of this._childInstances!) { + child.root()!.remove(); + child.unmount(); + } + this._childInstances!.length = 0; + } + + onAdd(idx: number, value: T) { const child = this._childCreator(value); this._childInstances!.splice(idx, 0, child); insertAt(this._root!, idx, mountView(child, this._mountArgs)); } - protected onRemove(idx: number, value: T) { + onRemove(idx: number, value: T) { const [child] = this._childInstances!.splice(idx, 1); child.root()!.remove(); child.unmount(); } - protected onMove(fromIdx: number, toIdx: number, value: T) { + onMove(fromIdx: number, toIdx: number, value: T) { const [child] = this._childInstances!.splice(fromIdx, 1); this._childInstances!.splice(toIdx, 0, child); child.root()!.remove(); insertAt(this._root!, toIdx, child.root()! as Element); } - protected onUpdate(i: number, value: T, params: any) { + onUpdate(i: number, value: T, params: any) { if (this._childInstances) { const instance = this._childInstances![i]; instance && instance.update(value, params); diff --git a/src/platform/web/ui/session/room/TimelineView.ts b/src/platform/web/ui/session/room/TimelineView.ts index a4e143aa..da3dc537 100644 --- a/src/platform/web/ui/session/room/TimelineView.ts +++ b/src/platform/web/ui/session/room/TimelineView.ts @@ -26,7 +26,7 @@ import {MissingAttachmentView} from "./timeline/MissingAttachmentView.js"; import {AnnouncementView} from "./timeline/AnnouncementView.js"; import {RedactedView} from "./timeline/RedactedView.js"; import {SimpleTile} from "../../../../../domain/session/room/timeline/tiles/SimpleTile.js"; -import {BaseObservableList as ObservableList} from "../../../../../observable/list/BaseObservableList.js"; +import {BaseObservableList as ObservableList} from "../../../../../observable/list/BaseObservableList"; //import {TimelineViewModel} from "../../../../../domain/session/room/timeline/TimelineViewModel.js"; export interface TimelineViewModel extends IObservableValue { @@ -211,7 +211,12 @@ class TilesListView extends ListView { this.onChanged = onChanged; } - protected onUpdate(index: number, value: SimpleTile, param: any) { + onReset() { + super.onReset(); + this.onChanged(); + } + + onUpdate(index: number, value: SimpleTile, param: any) { if (param === "shape") { const ExpectedClass = viewClassForEntry(value); const child = this.getChildInstanceByIndex(index); @@ -227,17 +232,17 @@ class TilesListView extends ListView { this.onChanged(); } - protected onAdd(idx: number, value: SimpleTile) { + onAdd(idx: number, value: SimpleTile) { super.onAdd(idx, value); this.onChanged(); } - protected onRemove(idx: number, value: SimpleTile) { + onRemove(idx: number, value: SimpleTile) { super.onRemove(idx, value); this.onChanged(); } - protected onMove(fromIdx: number, toIdx: number, value: SimpleTile) { + onMove(fromIdx: number, toIdx: number, value: SimpleTile) { super.onMove(fromIdx, toIdx, value); this.onChanged(); }