Dynamic scaling of visualizer and resizable window
Summary: Fixes https://fb.workplace.com/groups/443457641253219/permalink/480446154221034/ Reviewed By: mweststrate Differential Revision: D42095625 fbshipit-source-id: 364577141f2819dd22b0b499b11770d0bb88b1f5
This commit is contained in:
committed by
Facebook GitHub Bot
parent
e65c190136
commit
989797a225
@@ -19,16 +19,18 @@ import {UIDebuggerMenuItem} from './util/UIDebuggerMenuItem';
|
|||||||
export const Visualization2D: React.FC<
|
export const Visualization2D: React.FC<
|
||||||
{
|
{
|
||||||
rootId: Id;
|
rootId: Id;
|
||||||
|
width: number;
|
||||||
nodes: Map<Id, UINode>;
|
nodes: Map<Id, UINode>;
|
||||||
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, width, nodes, selectedNode, onSelectNode, modifierPressed}) => {
|
||||||
const rootNodeRef = useRef<HTMLDivElement>();
|
const rootNodeRef = useRef<HTMLDivElement>();
|
||||||
const instance = usePlugin(plugin);
|
const instance = usePlugin(plugin);
|
||||||
|
|
||||||
const snapshot = useValue(instance.snapshot);
|
const snapshot = useValue(instance.snapshot);
|
||||||
|
const snapshotNode = snapshot && nodes.get(snapshot.nodeId);
|
||||||
const focusedNodeId = useValue(instance.uiState.focusedNode);
|
const focusedNodeId = useValue(instance.uiState.focusedNode);
|
||||||
|
|
||||||
const focusState = useMemo(() => {
|
const focusState = useMemo(() => {
|
||||||
@@ -40,7 +42,12 @@ export const Visualization2D: React.FC<
|
|||||||
const mouseListener = throttle((ev: MouseEvent) => {
|
const mouseListener = throttle((ev: MouseEvent) => {
|
||||||
const domRect = rootNodeRef.current?.getBoundingClientRect();
|
const domRect = rootNodeRef.current?.getBoundingClientRect();
|
||||||
|
|
||||||
if (!focusState || !domRect || instance.uiState.isContextMenuOpen.get()) {
|
if (
|
||||||
|
!focusState ||
|
||||||
|
!domRect ||
|
||||||
|
instance.uiState.isContextMenuOpen.get() ||
|
||||||
|
!snapshotNode
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const rawMouse = {x: ev.clientX, y: ev.clientY};
|
const rawMouse = {x: ev.clientX, y: ev.clientY};
|
||||||
@@ -51,6 +58,8 @@ export const Visualization2D: React.FC<
|
|||||||
|
|
||||||
//make the mouse coord relative to the dom rect of the visualizer
|
//make the mouse coord relative to the dom rect of the visualizer
|
||||||
|
|
||||||
|
const pxScaleFactor = calcPxScaleFactor(snapshotNode.bounds, width);
|
||||||
|
|
||||||
const offsetMouse = offsetCoordinate(rawMouse, domRect);
|
const offsetMouse = offsetCoordinate(rawMouse, domRect);
|
||||||
const scaledMouse = {
|
const scaledMouse = {
|
||||||
x: offsetMouse.x * pxScaleFactor,
|
x: offsetMouse.x * pxScaleFactor,
|
||||||
@@ -78,22 +87,27 @@ export const Visualization2D: React.FC<
|
|||||||
focusState,
|
focusState,
|
||||||
nodes,
|
nodes,
|
||||||
instance.uiState.isContextMenuOpen,
|
instance.uiState.isContextMenuOpen,
|
||||||
|
width,
|
||||||
|
snapshotNode,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (!focusState) {
|
if (!focusState || !snapshotNode) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const snapshotNode = snapshot && nodes.get(snapshot.nodeId);
|
const pxScaleFactor = calcPxScaleFactor(snapshotNode.bounds, width);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ContextMenu nodes={nodes}>
|
<ContextMenu nodes={nodes}>
|
||||||
<div
|
<div
|
||||||
//this div is to ensure that the size of the visualiser doesnt change when focusings on a subtree
|
//this div is to ensure that the size of the visualiser doesnt change when focusings on a subtree
|
||||||
style={{
|
style={
|
||||||
|
{
|
||||||
|
[pxScaleFactorCssVar]: pxScaleFactor,
|
||||||
width: toPx(focusState.actualRoot.bounds.width),
|
width: toPx(focusState.actualRoot.bounds.width),
|
||||||
height: toPx(focusState.actualRoot.bounds.height),
|
height: toPx(focusState.actualRoot.bounds.height),
|
||||||
}}>
|
} as React.CSSProperties
|
||||||
|
}>
|
||||||
<div
|
<div
|
||||||
ref={rootNodeRef as any}
|
ref={rootNodeRef as any}
|
||||||
onMouseLeave={(e) => {
|
onMouseLeave={(e) => {
|
||||||
@@ -342,6 +356,8 @@ const NodeBorder = styled.div<{tags: Tag[]; hovered: boolean}>((props) => ({
|
|||||||
const longHoverDelay = 200;
|
const longHoverDelay = 200;
|
||||||
const outerBorderWidth = '10px';
|
const outerBorderWidth = '10px';
|
||||||
const outerBorderOffset = `-${outerBorderWidth}`;
|
const outerBorderOffset = `-${outerBorderWidth}`;
|
||||||
|
const pxScaleFactorCssVar = '--pxScaleFactor';
|
||||||
|
const MouseThrottle = 32;
|
||||||
|
|
||||||
//this is the thick black border around the whole vizualization, the border goes around the content
|
//this is the thick black border around the whole vizualization, the border goes around the content
|
||||||
//hence the top,left,right,botton being negative to increase its size
|
//hence the top,left,right,botton being negative to increase its size
|
||||||
@@ -358,11 +374,8 @@ const OuterBorder = styled.div({
|
|||||||
borderRadius: '10px',
|
borderRadius: '10px',
|
||||||
});
|
});
|
||||||
|
|
||||||
const pxScaleFactor = 2;
|
|
||||||
const MouseThrottle = 32;
|
|
||||||
|
|
||||||
function toPx(n: number) {
|
function toPx(n: number) {
|
||||||
return `${n / pxScaleFactor}px`;
|
return `calc(${n}px / var(${pxScaleFactorCssVar})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function toNestedNode(
|
function toNestedNode(
|
||||||
@@ -506,3 +519,7 @@ function offsetCoordinate(
|
|||||||
y: coordinate.y - offset.y,
|
y: coordinate.y - offset.y,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function calcPxScaleFactor(snapshotBounds: Bounds, availableWidth: number) {
|
||||||
|
return snapshotBounds.width / availableWidth;
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,7 +9,13 @@
|
|||||||
|
|
||||||
import React, {useState} from 'react';
|
import React, {useState} from 'react';
|
||||||
import {plugin} from '../index';
|
import {plugin} from '../index';
|
||||||
import {DetailSidebar, Layout, usePlugin, useValue} from 'flipper-plugin';
|
import {
|
||||||
|
DetailSidebar,
|
||||||
|
Layout,
|
||||||
|
usePlugin,
|
||||||
|
useValue,
|
||||||
|
_Sidebar as ResizablePanel,
|
||||||
|
} from 'flipper-plugin';
|
||||||
import {useHotkeys} from 'react-hotkeys-hook';
|
import {useHotkeys} from 'react-hotkeys-hook';
|
||||||
import {Id, Metadata, MetadataId, UINode} from '../types';
|
import {Id, Metadata, MetadataId, UINode} from '../types';
|
||||||
import {PerfStats} from './PerfStats';
|
import {PerfStats} from './PerfStats';
|
||||||
@@ -30,6 +36,8 @@ export function Component() {
|
|||||||
const [showPerfStats, setShowPerfStats] = useState(false);
|
const [showPerfStats, setShowPerfStats] = useState(false);
|
||||||
const [selectedNode, setSelectedNode] = useState<Id | undefined>(undefined);
|
const [selectedNode, setSelectedNode] = useState<Id | undefined>(undefined);
|
||||||
|
|
||||||
|
const [visualiserWidth, setVisualiserWidth] = useState(500);
|
||||||
|
|
||||||
useHotkeys('ctrl+i', () => setShowPerfStats((show) => !show));
|
useHotkeys('ctrl+i', () => setShowPerfStats((show) => !show));
|
||||||
|
|
||||||
const {ctrlPressed} = useKeyboardModifiers();
|
const {ctrlPressed} = useKeyboardModifiers();
|
||||||
@@ -53,13 +61,24 @@ export function Component() {
|
|||||||
</Layout.ScrollContainer>
|
</Layout.ScrollContainer>
|
||||||
</Layout.Container>
|
</Layout.Container>
|
||||||
|
|
||||||
|
<ResizablePanel
|
||||||
|
position="right"
|
||||||
|
minWidth={200}
|
||||||
|
width={visualiserWidth}
|
||||||
|
maxWidth={800}
|
||||||
|
onResize={(width) => {
|
||||||
|
setVisualiserWidth(width);
|
||||||
|
}}
|
||||||
|
gutter>
|
||||||
<Visualization2D
|
<Visualization2D
|
||||||
rootId={rootId}
|
rootId={rootId}
|
||||||
|
width={visualiserWidth}
|
||||||
nodes={nodes}
|
nodes={nodes}
|
||||||
selectedNode={selectedNode}
|
selectedNode={selectedNode}
|
||||||
onSelectNode={setSelectedNode}
|
onSelectNode={setSelectedNode}
|
||||||
modifierPressed={ctrlPressed}
|
modifierPressed={ctrlPressed}
|
||||||
/>
|
/>
|
||||||
|
</ResizablePanel>
|
||||||
<DetailSidebar width={350}>
|
<DetailSidebar width={350}>
|
||||||
<Inspector
|
<Inspector
|
||||||
metadata={metadata}
|
metadata={metadata}
|
||||||
|
|||||||
Reference in New Issue
Block a user