Remove per node snapshot in favour of single top level snapshot

Summary: In order to support focus mode we need to have only 1 snapshot. In practice this is the case but we are making this more apparant in this diff.

Reviewed By: lblasa

Differential Revision: D41493003

fbshipit-source-id: 19ed7213d15adaea4732f4ec60309efa8dae6f94
This commit is contained in:
Luke De Feo
2022-11-24 09:23:16 -08:00
committed by Facebook GitHub Bot
parent b576060339
commit 01f7fa34e5
3 changed files with 22 additions and 37 deletions

View File

@@ -8,17 +8,9 @@
*/ */
import React, {useEffect, useMemo, useRef, useState} from 'react'; import React, {useEffect, useMemo, useRef, useState} from 'react';
import { import {Bounds, Coordinate, Id, NestedNode, Tag, UINode} from '../types';
Bounds,
Coordinate,
Id,
NestedNode,
Snapshot,
Tag,
UINode,
} from '../types';
import {styled, theme, usePlugin} from 'flipper-plugin'; import {styled, theme, usePlugin, useValue} from 'flipper-plugin';
import {plugin} from '../index'; import {plugin} from '../index';
import {throttle, isEqual, head} from 'lodash'; import {throttle, isEqual, head} from 'lodash';
@@ -26,23 +18,16 @@ export const Visualization2D: React.FC<
{ {
rootId: Id; rootId: Id;
nodes: Map<Id, UINode>; nodes: Map<Id, UINode>;
snapshots: Map<Id, Snapshot>;
selectedNode?: Id; selectedNode?: Id;
onSelectNode: (id?: Id) => void; onSelectNode: (id?: Id) => void;
modifierPressed: boolean; modifierPressed: boolean;
} & React.HTMLAttributes<HTMLDivElement> } & React.HTMLAttributes<HTMLDivElement>
> = ({ > = ({rootId, nodes, selectedNode, onSelectNode, modifierPressed}) => {
rootId,
nodes,
snapshots,
selectedNode,
onSelectNode,
modifierPressed,
}) => {
const root = useMemo(() => toNestedNode(rootId, nodes), [rootId, nodes]); const root = useMemo(() => toNestedNode(rootId, nodes), [rootId, nodes]);
const rootNodeRef = useRef<HTMLDivElement>(); const rootNodeRef = useRef<HTMLDivElement>();
const instance = usePlugin(plugin); const instance = usePlugin(plugin);
const snapshot = useValue(instance.snapshot);
useEffect(() => { useEffect(() => {
const mouseListener = throttle((ev: MouseEvent) => { const mouseListener = throttle((ev: MouseEvent) => {
const domRect = rootNodeRef.current?.getBoundingClientRect(); const domRect = rootNodeRef.current?.getBoundingClientRect();
@@ -80,6 +65,7 @@ export const Visualization2D: React.FC<
return null; return null;
} }
const snapshotNode = snapshot && nodes.get(snapshot.nodeId);
return ( return (
<div <div
ref={rootNodeRef as any} ref={rootNodeRef as any}
@@ -100,10 +86,18 @@ export const Visualization2D: React.FC<
height: toPx(root.bounds.height), height: toPx(root.bounds.height),
overflow: 'hidden', overflow: 'hidden',
}}> }}>
{snapshot && snapshotNode && (
<img
src={'data:image/png;base64,' + snapshot.base64Image}
style={{
width: toPx(snapshotNode.bounds.width),
height: toPx(snapshotNode.bounds.height),
}}
/>
)}
<OuterBorder /> <OuterBorder />
<MemoedVisualizationNode2D <MemoedVisualizationNode2D
node={root} node={root}
snapshots={snapshots}
selectedNode={selectedNode} selectedNode={selectedNode}
onSelectNode={onSelectNode} onSelectNode={onSelectNode}
modifierPressed={modifierPressed} modifierPressed={modifierPressed}
@@ -125,18 +119,15 @@ const MemoedVisualizationNode2D = React.memo(
function Visualization2DNode({ function Visualization2DNode({
node, node,
snapshots,
selectedNode, selectedNode,
onSelectNode, onSelectNode,
modifierPressed, modifierPressed,
}: { }: {
node: NestedNode; node: NestedNode;
snapshots: Map<Id, Snapshot>;
modifierPressed: boolean; modifierPressed: boolean;
selectedNode?: Id; selectedNode?: Id;
onSelectNode: (id?: Id) => void; onSelectNode: (id?: Id) => void;
}) { }) {
const snapshot = snapshots.get(node.id);
const instance = usePlugin(plugin); const instance = usePlugin(plugin);
const [isHovered, setIsHovered] = useState(false); const [isHovered, setIsHovered] = useState(false);
@@ -174,7 +165,6 @@ function Visualization2DNode({
<MemoedVisualizationNode2D <MemoedVisualizationNode2D
key={child.id} key={child.id}
node={child} node={child}
snapshots={snapshots}
onSelectNode={onSelectNode} onSelectNode={onSelectNode}
selectedNode={selectedNode} selectedNode={selectedNode}
modifierPressed={modifierPressed} modifierPressed={modifierPressed}
@@ -210,12 +200,6 @@ function Visualization2DNode({
} }
}}> }}>
<NodeBorder hovered={isHovered} tags={node.tags}></NodeBorder> <NodeBorder hovered={isHovered} tags={node.tags}></NodeBorder>
{snapshot && (
<img
src={'data:image/png;base64,' + snapshot}
style={{maxWidth: '100%'}}
/>
)}
{isHovered && <p style={{float: 'right'}}>{node.name}</p>} {isHovered && <p style={{float: 'right'}}>{node.name}</p>}
{children} {children}
</div> </div>

View File

@@ -24,7 +24,6 @@ export function Component() {
const rootId = useValue(instance.rootId); const rootId = useValue(instance.rootId);
const nodes: Map<Id, UINode> = useValue(instance.nodes); const nodes: Map<Id, UINode> = useValue(instance.nodes);
const metadata: Map<MetadataId, Metadata> = useValue(instance.metadata); const metadata: Map<MetadataId, Metadata> = useValue(instance.metadata);
const snapshots: Map<Id, Snapshot> = useValue(instance.snapshots);
const [showPerfStats, setShowPerfStats] = useState(false); const [showPerfStats, setShowPerfStats] = useState(false);
const [selectedNode, setSelectedNode] = useState<Id | undefined>(undefined); const [selectedNode, setSelectedNode] = useState<Id | undefined>(undefined);
@@ -70,7 +69,6 @@ export function Component() {
<Visualization2D <Visualization2D
rootId={rootId} rootId={rootId}
nodes={nodes} nodes={nodes}
snapshots={snapshots}
selectedNode={selectedNode} selectedNode={selectedNode}
onSelectNode={setSelectedNode} onSelectNode={setSelectedNode}
modifierPressed={ctrlPressed} modifierPressed={ctrlPressed}

View File

@@ -49,7 +49,9 @@ export function plugin(client: PluginClient<Events>) {
}); });
const nodes = createState<Map<Id, UINode>>(new Map()); const nodes = createState<Map<Id, UINode>>(new Map());
const snapshots = createState<Map<Id, Snapshot>>(new Map()); const snapshot = createState<{nodeId: Id; base64Image: Snapshot} | null>(
null,
);
const treeState = createState<TreeState>({expandedNodes: []}); const treeState = createState<TreeState>({expandedNodes: []});
@@ -71,9 +73,10 @@ export function plugin(client: PluginClient<Events>) {
const seenNodes = new Set<Id>(); const seenNodes = new Set<Id>();
client.onMessage('subtreeUpdate', (event) => { client.onMessage('subtreeUpdate', (event) => {
snapshots.update((draft) => { if (event.snapshot) {
draft.set(event.rootId, event.snapshot); snapshot.set({nodeId: event.rootId, base64Image: event.snapshot});
}); }
nodes.update((draft) => { nodes.update((draft) => {
event.nodes.forEach((node) => { event.nodes.forEach((node) => {
draft.set(node.id, node); draft.set(node.id, node);
@@ -105,7 +108,7 @@ export function plugin(client: PluginClient<Events>) {
rootId, rootId,
nodes, nodes,
metadata, metadata,
snapshots, snapshot,
hoveredNodes, hoveredNodes,
perfEvents, perfEvents,
treeState, treeState,