in desktop/flipper-plugin/src/data-source/DataSource.tsx [653:744]
processEvent(event: DataEvent<T>) {
const {_output: output, sortBy, filter} = this;
switch (event.type) {
case 'append': {
const {entry} = event;
entry.visible = filter ? filter(entry.value) : true;
if (!entry.visible) {
// not in filter? skip this entry
return;
}
if (!sortBy) {
// no sorting? insert at the end, or beginning
entry.approxIndex = output.length;
output.push(entry);
this.notifyItemShift(entry.approxIndex, 1);
} else {
this.insertSorted(entry);
}
break;
}
case 'update': {
const {entry} = event;
entry.visible = filter ? filter(entry.value) : true;
// short circuit; no view active so update straight away
if (!filter && !sortBy) {
output[event.index].approxIndex = event.index;
this.notifyItemUpdated(event.index);
} else if (!event.oldVisible) {
if (!entry.visible) {
// Done!
} else {
// insertion, not visible before
this.insertSorted(entry);
}
} else {
// Entry was visible previously
const existingIndex = this.getSortedIndex(entry, event.oldValue);
if (!entry.visible) {
// Remove from output
output.splice(existingIndex, 1);
this.notifyItemShift(existingIndex, -1);
} else {
// Entry was and still is visible
if (
!this.sortBy ||
this.sortBy(event.oldValue) === this.sortBy(entry.value)
) {
// Still at same position, so done!
this.notifyItemUpdated(existingIndex);
} else {
// item needs to be moved cause of sorting
// possible optimization: if we discover that old and new index would be the same,
// despite different sort values, we could still emit only an update instead of two shifts
output.splice(existingIndex, 1);
this.notifyItemShift(existingIndex, -1);
// find new sort index
this.insertSorted(entry);
}
}
}
break;
}
case 'remove': {
this.processRemoveEvent(event.index, event.entry);
break;
}
case 'shift': {
// no sorting? then all items are removed from the start so optimize for that
if (!sortBy) {
let amount = 0;
if (!filter) {
amount = event.amount;
} else {
// if there is a filter, count the visibles and shift those
for (let i = 0; i < event.entries.length; i++)
if (event.entries[i].visible) amount++;
}
output.splice(0, amount);
this.notifyItemShift(0, -amount);
} else {
// we have sorting, so we need to remove item by item
// we do this backward, so that approxIndex is more likely to be correct
for (let i = event.entries.length - 1; i >= 0; i--) {
this.processRemoveEvent(i, event.entries[i]);
}
}
break;
}
default:
throw new Error('unknown event type');
}
}