mirror of
https://github.com/pezkuwichain/pezkuwi-telemetry.git
synced 2026-04-23 06:08:04 +00:00
Prevent nodes out of viewport triggering render (#296)
* Prevent nodes out of viewport triggering render * Update frontend/src/common/SortedCollection.ts Co-authored-by: David <dvdplm@gmail.com> * Tweak the comment on `setFocus`, move it closer to `ref` and `hasChangedSince` * Switch `SortedCollection.ref()` to a getter Co-authored-by: David <dvdplm@gmail.com>
This commit is contained in:
@@ -149,7 +149,7 @@ export class Connection {
|
||||
|
||||
public handleMessages = (messages: FeedMessage.Message[]) => {
|
||||
const { nodes, chains, sortBy, selectedColumns } = this.state;
|
||||
const ref = nodes.ref();
|
||||
const { ref } = nodes;
|
||||
|
||||
const updateState: UpdateBound = (state) => {
|
||||
this.state = this.update(state);
|
||||
|
||||
@@ -97,11 +97,27 @@ export namespace SortedCollection {
|
||||
export type StateRef = Opaque<number, 'SortedCollection.StateRef'>;
|
||||
}
|
||||
|
||||
interface Focus {
|
||||
start: number;
|
||||
end: number;
|
||||
}
|
||||
|
||||
export class SortedCollection<Item extends { id: number }> {
|
||||
// Comparator function used to sort the collection
|
||||
private compare: Compare<Item>;
|
||||
// Mapping item `id` to the `Item`, this uses array as a structure with
|
||||
// the assumption that `id`s provided are increments from `0`, and that
|
||||
// vacant `id`s will be re-used in the future.
|
||||
private map = Array<Maybe<Item>>();
|
||||
// Actual sorted list of `Item`s.
|
||||
private list = Array<Item>();
|
||||
// Internal tracker for changes, this number increments whenever the
|
||||
// order of the **focused** elements in the collection changes
|
||||
private changeRef = 0;
|
||||
// Marks the range of indicies that are focused for tracking.
|
||||
// **Note:** `start` is inclusive, while `end` is exclusive (much like
|
||||
// `Array.slice()`).
|
||||
private focus: Focus = { start: 0, end: 0 };
|
||||
|
||||
constructor(compare: Compare<Item>) {
|
||||
this.compare = compare;
|
||||
@@ -114,10 +130,6 @@ export class SortedCollection<Item extends { id: number }> {
|
||||
this.changeRef += 1;
|
||||
}
|
||||
|
||||
public ref(): SortedCollection.StateRef {
|
||||
return this.changeRef as SortedCollection.StateRef;
|
||||
}
|
||||
|
||||
public add(item: Item) {
|
||||
if (this.map.length <= item.id) {
|
||||
// Grow map if item.id would be out of scope
|
||||
@@ -131,9 +143,11 @@ export class SortedCollection<Item extends { id: number }> {
|
||||
|
||||
this.map[item.id] = item;
|
||||
|
||||
sortedInsert(item, this.list, this.compare);
|
||||
const index = sortedInsert(item, this.list, this.compare);
|
||||
|
||||
this.changeRef += 1;
|
||||
if (index < this.focus.end) {
|
||||
this.changeRef += 1;
|
||||
}
|
||||
}
|
||||
|
||||
public remove(id: number) {
|
||||
@@ -147,7 +161,9 @@ export class SortedCollection<Item extends { id: number }> {
|
||||
this.list.splice(index, 1);
|
||||
this.map[id] = null;
|
||||
|
||||
this.changeRef += 1;
|
||||
if (index < this.focus.end) {
|
||||
this.changeRef += 1;
|
||||
}
|
||||
}
|
||||
|
||||
public get(id: number): Maybe<Item> {
|
||||
@@ -184,7 +200,13 @@ export class SortedCollection<Item extends { id: number }> {
|
||||
const newIndex = sortedInsert(item, this.list, this.compare);
|
||||
|
||||
if (newIndex !== index) {
|
||||
this.changeRef += 1;
|
||||
const outOfFocus =
|
||||
(index < this.focus.start && newIndex < this.focus.start) ||
|
||||
(index >= this.focus.end && newIndex >= this.focus.end);
|
||||
|
||||
if (!outOfFocus) {
|
||||
this.changeRef += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,6 +229,7 @@ export class SortedCollection<Item extends { id: number }> {
|
||||
public mutEachAndSort(mutator: (item: Item) => void) {
|
||||
this.list.forEach(mutator);
|
||||
this.list.sort(this.compare);
|
||||
this.changeRef += 1;
|
||||
}
|
||||
|
||||
public clear() {
|
||||
@@ -216,6 +239,18 @@ export class SortedCollection<Item extends { id: number }> {
|
||||
this.changeRef += 1;
|
||||
}
|
||||
|
||||
// Set a new `Focus`. Any changes to the order of items within the `Focus`
|
||||
// will increment `changeRef`.
|
||||
public setFocus(start: number, end: number) {
|
||||
this.focus = { start, end };
|
||||
}
|
||||
|
||||
// Get the reference to current ordering state of focused items.
|
||||
public get ref(): SortedCollection.StateRef {
|
||||
return this.changeRef as SortedCollection.StateRef;
|
||||
}
|
||||
|
||||
// Check if order of focused items has changed since obtaining a `ref`.
|
||||
public hasChangedSince(ref: SortedCollection.StateRef): boolean {
|
||||
return this.changeRef > ref;
|
||||
}
|
||||
|
||||
@@ -52,11 +52,11 @@ export class List extends React.Component<List.Props, {}> {
|
||||
}
|
||||
|
||||
public render() {
|
||||
const { selectedColumns } = this.props.appState;
|
||||
const { pins, sortBy } = this.props;
|
||||
const { filter } = this.state;
|
||||
const { pins, sortBy, appState } = this.props;
|
||||
const { selectedColumns } = appState;
|
||||
const { filter, listStart, listEnd } = this.state;
|
||||
|
||||
let nodes = this.props.appState.nodes.sorted();
|
||||
let nodes = appState.nodes.sorted();
|
||||
|
||||
if (filter != null) {
|
||||
nodes = nodes.filter(filter);
|
||||
@@ -73,10 +73,13 @@ export class List extends React.Component<List.Props, {}> {
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
// With filter present, we can no longer guarantee that focus corresponds
|
||||
// to rendering view, so we put the whole list in focus
|
||||
appState.nodes.setFocus(0, nodes.length);
|
||||
} else {
|
||||
appState.nodes.setFocus(listStart, listEnd);
|
||||
}
|
||||
|
||||
const { listStart, listEnd } = this.state;
|
||||
|
||||
const height = TH_HEIGHT + nodes.length * TR_HEIGHT;
|
||||
const transform = `translateY(${listStart * TR_HEIGHT}px)`;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user