MappedList.findAndUpdate
This commit is contained in:
parent
ce7147e463
commit
a5d5c55835
1 changed files with 77 additions and 2 deletions
|
@ -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);
|
||||||
|
},
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue