diff --git a/src/matrix/room/timeline/Timeline.js b/src/matrix/room/timeline/Timeline.js index dffe973b..6614e58b 100644 --- a/src/matrix/room/timeline/Timeline.js +++ b/src/matrix/room/timeline/Timeline.js @@ -90,27 +90,23 @@ export class Timeline { } _applyAndEmitLocalRelationChange(pe, updater) { - // first, look in local entries (separately, as it has its own update mechanism) + const updateOrFalse = e => { + const params = updater(e); + return params ? params : false; + }; + // first, look in local entries based on txn id const foundInLocalEntries = this._localEntries.findAndUpdate( e => e.id === pe.relatedTxnId, - e => { - const params = updater(e); - return params ? params : false; - }, + updateOrFalse, ); - // now look in remote entries + // now look in remote entries based on event id if (!foundInLocalEntries && pe.relatedEventId) { // TODO: ideally iterate in reverse as target is likely to be most recent, // but not easy through ObservableList contract - for (const entry of this._remoteEntries) { - if (pe.relatedEventId === entry.id) { - const params = updater(entry); - if (params) { - this._remoteEntries.update(entry, params); - } - return; - } - } + this._remoteEntries.findAndUpdate( + e => e.id === pe.relatedEventId, + updateOrFalse + ); } } diff --git a/src/observable/list/MappedList.js b/src/observable/list/MappedList.js index 1aed299f..ddb61384 100644 --- a/src/observable/list/MappedList.js +++ b/src/observable/list/MappedList.js @@ -16,6 +16,7 @@ limitations under the License. */ import {BaseObservableList} from "./BaseObservableList.js"; +import {findAndUpdateInArray} from "./common.js"; export class MappedList extends BaseObservableList { constructor(sourceList, mapper, updater, removeCallback) { @@ -80,18 +81,7 @@ export class MappedList extends BaseObservableList { } findAndUpdate(predicate, updater) { - const index = this._mappedValues.findIndex(predicate); - if (index !== -1) { - const mappedValue = this._mappedValues[index]; - // allow bailing out of sending an emit if updater determined its not needed - const params = updater(mappedValue); - if (params !== false) { - this.emitUpdate(index, mappedValue, params); - } - // found - return true; - } - return false; + return findAndUpdateInArray(predicate, this._mappedValues, this, updater); } get length() { diff --git a/src/observable/list/SortedArray.js b/src/observable/list/SortedArray.js index f040702d..cf17449b 100644 --- a/src/observable/list/SortedArray.js +++ b/src/observable/list/SortedArray.js @@ -16,6 +16,7 @@ limitations under the License. import {BaseObservableList} from "./BaseObservableList.js"; import {sortedIndex} from "../../utils/sortedIndex.js"; +import {findAndUpdateInArray} from "./common.js"; export class SortedArray extends BaseObservableList { constructor(comparator) { @@ -41,20 +42,8 @@ export class SortedArray extends BaseObservableList { } } - findAndUpdate(newValue, updater) { - const index = this.indexOf(newValue); - if (index !== -1) { - const oldValue = this._items[index]; - // allow bailing out of sending an emit if updater determined its not needed - const params = updater(oldValue, newValue); - if (params !== false) { - this._items[index] = newValue; - this.emitUpdate(index, newValue, params); - } - // found - return true; - } - return false; + findAndUpdate(predicate, updater) { + return findAndUpdateInArray(predicate, this._items, this, updater); } update(item, updateParams = null, previousCallback = null) { diff --git a/src/observable/list/common.js b/src/observable/list/common.js new file mode 100644 index 00000000..8dbf7873 --- /dev/null +++ b/src/observable/list/common.js @@ -0,0 +1,32 @@ +/* +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. +*/ + +/* inline update of item in collection backed by array, without replacing the preexising item */ +export function findAndUpdateInArray(predicate, array, observable, updater) { + const index = array.findIndex(predicate); + if (index !== -1) { + const value = array[index]; + // allow bailing out of sending an emit if updater determined its not needed + const params = updater(value); + if (params !== false) { + observable.emitUpdate(index, value, params); + } + // found + return true; + } + return false; +} \ No newline at end of file