MappedList.findAndUpdate

This commit is contained in:
Bruno Windels 2021-05-26 13:08:33 +02:00
parent ce7147e463
commit a5d5c55835

View File

@ -1,5 +1,6 @@
/* /*
Copyright 2020 Bruno Windels <bruno@windels.cloud> Copyright 2020 Bruno Windels <bruno@windels.cloud>
Copyright 2021 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -17,11 +18,12 @@ limitations under the License.
import {BaseObservableList} from "./BaseObservableList.js"; import {BaseObservableList} from "./BaseObservableList.js";
export class MappedList extends BaseObservableList { export class MappedList extends BaseObservableList {
constructor(sourceList, mapper, updater) { constructor(sourceList, mapper, updater, removeCallback) {
super(); super();
this._sourceList = sourceList; this._sourceList = sourceList;
this._mapper = mapper; this._mapper = mapper;
this._updater = updater; this._updater = updater;
this._removeCallback = removeCallback;
this._sourceUnsubscribe = null; this._sourceUnsubscribe = null;
this._mappedValues = null; this._mappedValues = null;
} }
@ -56,6 +58,9 @@ export class MappedList extends BaseObservableList {
onRemove(index) { onRemove(index) {
const mappedValue = this._mappedValues[index]; const mappedValue = this._mappedValues[index];
this._mappedValues.splice(index, 1); this._mappedValues.splice(index, 1);
if (this._removeCallback) {
this._removeCallback(mappedValue);
}
this.emitRemove(index, mappedValue); this.emitRemove(index, mappedValue);
} }
@ -70,6 +75,21 @@ export class MappedList extends BaseObservableList {
this._sourceUnsubscribe(); this._sourceUnsubscribe();
} }
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;
}
get length() { get length() {
return this._mappedValues.length; return this._mappedValues.length;
} }
@ -79,6 +99,8 @@ export class MappedList extends BaseObservableList {
} }
} }
import {ObservableArray} from "./ObservableArray.js";
export async function tests() { export async function tests() {
class MockList extends BaseObservableList { class MockList extends BaseObservableList {
get length() { get length() {
@ -126,6 +148,59 @@ export async function tests() {
source.emitUpdate(0, 7); source.emitUpdate(0, 7);
assert(fired); assert(fired);
unsubscribe(); unsubscribe();
},
"test findAndUpdate not found": assert => {
const source = new ObservableArray([1, 3, 4]);
const mapped = new MappedList(
source,
n => {return n*n;}
);
mapped.subscribe({
onUpdate() { assert.fail(); }
});
assert.equal(mapped.findAndUpdate(
n => n === 100,
() => assert.fail()
), false);
},
"test findAndUpdate found but updater bails out of update": assert => {
const source = new ObservableArray([1, 3, 4]);
const mapped = new MappedList(
source,
n => {return n*n;}
);
mapped.subscribe({
onUpdate() { assert.fail(); }
});
let fired = false;
assert.equal(mapped.findAndUpdate(
n => n === 9,
n => {
assert.equal(n, 9);
fired = true;
return false;
} }
), true);
assert.equal(fired, true);
},
"test findAndUpdate emits update": assert => {
const source = new ObservableArray([1, 3, 4]);
const mapped = new MappedList(
source,
n => {return n*n;}
);
let fired = false;
mapped.subscribe({
onUpdate(idx, n, params) {
assert.equal(idx, 1);
assert.equal(n, 9);
assert.equal(params, "param");
fired = true;
}
});
assert.equal(mapped.findAndUpdate(n => n === 9, () => "param"), true);
assert.equal(fired, true);
},
}; };
} }