mirror of
https://github.com/vector-im/hydrogen-web.git
synced 2024-12-23 11:35:04 +01:00
map operator for observable lists
This commit is contained in:
parent
0b5c2f9273
commit
6f650d19b1
@ -5,6 +5,7 @@ import BaseObservableMap from "./map/BaseObservableMap.js";
|
|||||||
// re-export "root" (of chain) collections
|
// re-export "root" (of chain) collections
|
||||||
export { default as ObservableArray } from "./list/ObservableArray.js";
|
export { default as ObservableArray } from "./list/ObservableArray.js";
|
||||||
export { default as SortedArray } from "./list/SortedArray.js";
|
export { default as SortedArray } from "./list/SortedArray.js";
|
||||||
|
export { default as MappedList } from "./list/MappedList.js";
|
||||||
export { default as ObservableMap } from "./map/ObservableMap.js";
|
export { default as ObservableMap } from "./map/ObservableMap.js";
|
||||||
|
|
||||||
// avoid circular dependency between these classes
|
// avoid circular dependency between these classes
|
||||||
|
115
src/observable/list/MappedList.js
Normal file
115
src/observable/list/MappedList.js
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
import BaseObservableList from "./BaseObservableList.js";
|
||||||
|
|
||||||
|
export default class MappedList extends BaseObservableList {
|
||||||
|
constructor(sourceList, mapper, updater) {
|
||||||
|
super();
|
||||||
|
this._sourceList = sourceList;
|
||||||
|
this._mapper = mapper;
|
||||||
|
this._updater = updater;
|
||||||
|
this._sourceUnsubscribe = null;
|
||||||
|
this._mappedValues = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
onSubscribeFirst() {
|
||||||
|
this._sourceUnsubscribe = this._sourceList.subscribe(this);
|
||||||
|
this._mappedValues = [];
|
||||||
|
for (const item of this._sourceList) {
|
||||||
|
this._mappedValues.push(this._mapper(item));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onReset() {
|
||||||
|
this._mappedValues = [];
|
||||||
|
this.emitReset();
|
||||||
|
}
|
||||||
|
|
||||||
|
onAdd(index, value) {
|
||||||
|
const mappedValue = this._mapper(value);
|
||||||
|
this._mappedValues.splice(index, 0, mappedValue);
|
||||||
|
this.emitAdd(index, mappedValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
onUpdate(index, value, params) {
|
||||||
|
const mappedValue = this._mappedValues[index];
|
||||||
|
if (this._updater) {
|
||||||
|
this._updater(mappedValue, value);
|
||||||
|
}
|
||||||
|
this.emitUpdate(index, mappedValue, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
onRemove(index) {
|
||||||
|
const mappedValue = this._mappedValues[index];
|
||||||
|
this._mappedValues.splice(index, 1);
|
||||||
|
this.emitRemove(index, mappedValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
onMove(fromIdx, toIdx) {
|
||||||
|
const mappedValue = this._mappedValues[fromIdx];
|
||||||
|
this._mappedValues.splice(fromIdx, 1);
|
||||||
|
this._mappedValues.splice(toIdx, 0, mappedValue);
|
||||||
|
this.emitMove(fromIdx, toIdx, mappedValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
onUnsubscribeLast() {
|
||||||
|
this._sourceUnsubscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
get length() {
|
||||||
|
return this._mappedValues.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Symbol.iterator]() {
|
||||||
|
return this._mappedValues.values();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function tests() {
|
||||||
|
class MockList extends BaseObservableList {
|
||||||
|
get length() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
[Symbol.iterator]() {
|
||||||
|
return [].values();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
test_add(assert) {
|
||||||
|
const source = new MockList();
|
||||||
|
const mapped = new MappedList(source, n => {return {n: n*n};});
|
||||||
|
let fired = false;
|
||||||
|
const unsubscribe = mapped.subscribe({
|
||||||
|
onAdd(idx, value) {
|
||||||
|
fired = true;
|
||||||
|
assert.equal(idx, 0);
|
||||||
|
assert.equal(value.n, 36);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
source.emitAdd(0, 6);
|
||||||
|
assert(fired);
|
||||||
|
unsubscribe();
|
||||||
|
},
|
||||||
|
test_update(assert) {
|
||||||
|
const source = new MockList();
|
||||||
|
const mapped = new MappedList(
|
||||||
|
source,
|
||||||
|
n => {return {n: n*n};},
|
||||||
|
(o, n) => o.m = n*n
|
||||||
|
);
|
||||||
|
let fired = false;
|
||||||
|
const unsubscribe = mapped.subscribe({
|
||||||
|
onAdd() {},
|
||||||
|
onUpdate(idx, value) {
|
||||||
|
fired = true;
|
||||||
|
assert.equal(idx, 0);
|
||||||
|
assert.equal(value.n, 36);
|
||||||
|
assert.equal(value.m, 49);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
source.emitAdd(0, 6);
|
||||||
|
source.emitUpdate(0, 7);
|
||||||
|
assert(fired);
|
||||||
|
unsubscribe();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user