Add wireframe mode control

Summary:
This allows you to control how the wire frames are drawn, useful when there are lots of overalpping wireframes

Changelog: UIDebugger - Added wireframe mode control, useful when lots of overlapping wireframes

Reviewed By: aigoncharov

Differential Revision: D47949841

fbshipit-source-id: 72de7d085ca433557107ab0cc6e4399220836d9f
This commit is contained in:
Luke De Feo
2023-08-01 10:32:29 -07:00
committed by Facebook GitHub Bot
parent fb469faa1d
commit fb503a0a2f
6 changed files with 105 additions and 8 deletions

View File

@@ -9,7 +9,7 @@
import React, {useEffect, useMemo, useRef, useState} from 'react';
import {Bounds, Coordinate, Id, ClientNode} from '../../ClientTypes';
import {NestedNode, OnSelectNode} from '../../DesktopTypes';
import {NestedNode, OnSelectNode, WireFrameMode} from '../../DesktopTypes';
import {
produce,
@@ -42,6 +42,7 @@ export const Visualization2D: React.FC<
const selectedNodeId = useValue(instance.uiState.selectedNode);
const hoveredNodes = useValue(instance.uiState.hoveredNodes);
const hoveredNodeId = head(hoveredNodes);
const wireFrameMode = useValue(instance.uiState.wireFrameMode);
const [targetMode, setTargetMode] = useState<TargetModeState>({
state: 'disabled',
@@ -141,6 +142,8 @@ export const Visualization2D: React.FC<
return (
<Layout.Container>
<VisualiserControls
onSetWireFrameMode={instance.uiActions.onSetWireFrameMode}
wireFrameMode={wireFrameMode}
focusedNode={focusedNodeId}
selectedNode={selectedNodeId?.id}
setTargetMode={setTargetMode}
@@ -226,6 +229,9 @@ export const Visualization2D: React.FC<
/>
)}
<MemoedVisualizationNode2D
wireframeMode={wireFrameMode}
isSelectedOrChildOrSelected={false}
selectedNode={selectedNodeId?.id}
node={focusState.focusedRoot}
onSelectNode={onSelectNode}
/>
@@ -238,19 +244,30 @@ export const Visualization2D: React.FC<
const MemoedVisualizationNode2D = React.memo(
Visualization2DNode,
(prev, next) => {
return prev.node === next.node;
return (
prev.node === next.node &&
prev.selectedNode === next.selectedNode &&
prev.wireframeMode === next.wireframeMode
);
},
);
function Visualization2DNode({
wireframeMode,
isSelectedOrChildOrSelected,
selectedNode,
node,
onSelectNode,
}: {
wireframeMode: WireFrameMode;
isSelectedOrChildOrSelected: boolean;
selectedNode?: Id;
node: NestedNode;
onSelectNode: OnSelectNode;
}) {
const instance = usePlugin(plugin);
const isSelected = node.id === selectedNode;
const ref = useRef<HTMLDivElement>(null);
let nestedChildren: NestedNode[];
@@ -268,6 +285,9 @@ function Visualization2DNode({
const children = nestedChildren.map((child) => (
<MemoedVisualizationNode2D
wireframeMode={wireframeMode}
selectedNode={selectedNode}
isSelectedOrChildOrSelected={isSelected || isSelectedOrChildOrSelected}
key={child.id}
node={child}
onSelectNode={onSelectNode}
@@ -278,6 +298,11 @@ function Visualization2DNode({
node.id,
);
const showBorder =
wireframeMode === 'All' ||
(wireframeMode === 'SelectedAndChildren' && isSelectedOrChildOrSelected) ||
(wireframeMode === 'SelectedOnly' && isSelected);
return (
<div
role="button"
@@ -293,7 +318,7 @@ function Visualization2DNode({
opacity: isHighlighted ? 0.3 : 1,
backgroundColor: isHighlighted ? 'red' : 'transparent',
}}>
<NodeBorder />
{showBorder && <NodeBorder />}
{children}
</div>

View File

@@ -7,7 +7,7 @@
* @format
*/
import {Button, Slider, Tooltip, Typography} from 'antd';
import {Button, Dropdown, Menu, Slider, Tooltip, Typography} from 'antd';
import {Layout, produce, theme, usePlugin} from 'flipper-plugin';
import {Id} from '../../ClientTypes';
import {plugin} from '../../index';
@@ -16,10 +16,11 @@ import {
AimOutlined,
FullscreenExitOutlined,
FullscreenOutlined,
PicCenterOutlined,
} from '@ant-design/icons';
import {tracker} from '../../utils/tracker';
import {debounce} from 'lodash';
import {WireFrameMode} from '../../DesktopTypes';
export type TargetModeState =
| {
state: 'selected';
@@ -38,7 +39,11 @@ export function VisualiserControls({
setTargetMode,
selectedNode,
focusedNode,
wireFrameMode,
onSetWireFrameMode,
}: {
wireFrameMode: WireFrameMode;
onSetWireFrameMode: (mode: WireFrameMode) => void;
selectedNode?: Id;
focusedNode?: Id;
setTargetMode: (targetMode: TargetModeState) => void;
@@ -54,7 +59,7 @@ export function VisualiserControls({
: 'Remove focus';
const targetToolTip =
targetMode.state === 'disabled' ? 'TargetMode' : 'Exit target mode';
targetMode.state === 'disabled' ? 'Target Mode' : 'Exit target mode';
return (
<Layout.Right style={{padding: theme.space.medium}} gap="medium" center>
@@ -81,13 +86,43 @@ export function VisualiserControls({
targetMode.targetedNodes[value],
'visualiser',
);
debouncedReportTargetAdjusted();
}}
/>
)}
</Layout.Container>
<Layout.Horizontal gap="medium">
<Layout.Horizontal gap="medium" center>
<Dropdown
overlay={
<Menu>
<SelectableDropDownItem
onSelect={onSetWireFrameMode}
text="All"
selectedValue={wireFrameMode}
value="All"
/>
<SelectableDropDownItem
onSelect={onSetWireFrameMode}
text="Selected and children"
selectedValue={wireFrameMode}
value="SelectedAndChildren"
/>
<SelectableDropDownItem
onSelect={onSetWireFrameMode}
text="Selected only"
selectedValue={wireFrameMode}
value="SelectedOnly"
/>
</Menu>
}>
<Tooltip title="Wireframe Mode">
<Button shape="circle">
<PicCenterOutlined />
</Button>
</Tooltip>
</Dropdown>
<Tooltip title={targetToolTip}>
<Button
shape="circle"
@@ -145,6 +180,31 @@ export function VisualiserControls({
);
}
function SelectableDropDownItem<T>({
value,
selectedValue,
onSelect,
text,
}: {
value: T;
selectedValue: T;
onSelect: (value: T) => void;
text: string;
}) {
return (
<Menu.Item
style={{
color:
value === selectedValue ? theme.primaryColor : theme.textColorActive,
}}
onClick={() => {
onSelect(value);
}}>
{text}
</Menu.Item>
);
}
const debouncedReportTargetAdjusted = debounce(() => {
tracker.track('target-mode-adjusted', {});
}, 500);