Files
flipper/desktop/plugins/public/ui-debugger/index.tsx
Luke De Feo 3722ac1fea Permanent search bar
Summary: Out of the box the library search has some issues. when search matches it steals focus from the input. Eventually we want to customise the rendering of the tree items anyway so this lays the foundation for taht

Reviewed By: antonk52

Differential Revision: D41336524

fbshipit-source-id: 194f67023edd0675cd9bd8d6134260439c6b2785
2022-11-24 09:23:16 -08:00

117 lines
3.0 KiB
TypeScript

/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import {PluginClient, createState, createDataSource} from 'flipper-plugin';
import {
Events,
Id,
Metadata,
MetadataId,
PerfStatsEvent,
Snapshot,
TreeState,
UINode,
} from './types';
import './node_modules/react-complex-tree/lib/style.css';
export function plugin(client: PluginClient<Events>) {
const rootId = createState<Id | undefined>(undefined);
const metadata = createState<Map<MetadataId, Metadata>>(new Map());
const searchTerm = createState<string>('');
client.onMessage('init', (event) => {
rootId.set(event.rootId);
});
client.onMessage('metadataUpdate', (event) => {
if (!event.attributeMetadata) {
return;
}
metadata.update((draft) => {
for (const [_key, value] of Object.entries(event.attributeMetadata)) {
draft.set(value.id, value);
}
});
});
const perfEvents = createDataSource<PerfStatsEvent, 'txId'>([], {
key: 'txId',
limit: 10 * 1024,
});
client.onMessage('perfStats', (event) => {
perfEvents.append(event);
});
const nodes = createState<Map<Id, UINode>>(new Map());
const snapshots = createState<Map<Id, Snapshot>>(new Map());
const treeState = createState<TreeState>({expandedNodes: []});
//The reason for the array as that user could be hovering multiple overlapping nodes at once in the visualiser.
//The nodes are sorted by area since you most likely want to select the smallest node under your cursor
const hoveredNodes = createState<Id[]>([]);
client.onMessage('coordinateUpdate', (event) => {
nodes.update((draft) => {
const node = draft.get(event.nodeId);
if (!node) {
console.warn(`Coordinate update for non existing node `, event);
} else {
node.bounds.x = event.coordinate.x;
node.bounds.y = event.coordinate.y;
}
});
});
const seenNodes = new Set<Id>();
client.onMessage('subtreeUpdate', (event) => {
snapshots.update((draft) => {
draft.set(event.rootId, event.snapshot);
});
nodes.update((draft) => {
event.nodes.forEach((node) => {
draft.set(node.id, node);
});
});
treeState.update((draft) => {
for (const node of event.nodes) {
if (!seenNodes.has(node.id)) {
draft.expandedNodes.push(node.id);
}
seenNodes.add(node.id);
if (node.activeChild) {
const inactiveChildren = node.children.filter(
(child) => child !== node.activeChild,
);
draft.expandedNodes = draft.expandedNodes.filter(
(nodeId) => !inactiveChildren.includes(nodeId),
);
draft.expandedNodes.push(node.activeChild);
}
}
});
});
return {
rootId,
nodes,
metadata,
snapshots,
hoveredNodes,
perfEvents,
treeState,
searchTerm,
};
}
export {Component} from './components/main';