Summary: This mode is useless for leaves Reviewed By: aigoncharov Differential Revision: D47949539 fbshipit-source-id: 7f3ae6652ad696e9f550fe5b8f2298a1a3eff329
213 lines
5.7 KiB
TypeScript
213 lines
5.7 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 {Button, Dropdown, Menu, Slider, Tooltip, Typography} from 'antd';
|
|
import {Layout, produce, theme, usePlugin} from 'flipper-plugin';
|
|
import {ClientNode, Id} from '../../ClientTypes';
|
|
import {plugin} from '../../index';
|
|
import React from 'react';
|
|
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';
|
|
targetedNodes: Id[];
|
|
sliderPosition: number;
|
|
}
|
|
| {
|
|
state: 'active';
|
|
}
|
|
| {
|
|
state: 'disabled';
|
|
};
|
|
|
|
export function VisualiserControls({
|
|
targetMode,
|
|
setTargetMode,
|
|
selectedNode,
|
|
focusedNode,
|
|
wireFrameMode,
|
|
onSetWireFrameMode,
|
|
}: {
|
|
wireFrameMode: WireFrameMode;
|
|
onSetWireFrameMode: (mode: WireFrameMode) => void;
|
|
selectedNode?: ClientNode;
|
|
focusedNode?: Id;
|
|
setTargetMode: (targetMode: TargetModeState) => void;
|
|
targetMode: TargetModeState;
|
|
}) {
|
|
const instance = usePlugin(plugin);
|
|
|
|
const focusDisabled =
|
|
focusedNode == null &&
|
|
(selectedNode == null || selectedNode.children.length === 0);
|
|
const focusToolTip = focusDisabled
|
|
? 'Select a non leaf node to focus it'
|
|
: focusedNode == null
|
|
? 'Focus current node'
|
|
: 'Remove focus';
|
|
|
|
const targetToolTip =
|
|
targetMode.state === 'disabled' ? 'Target Mode' : 'Exit target mode';
|
|
|
|
return (
|
|
<Layout.Right style={{padding: theme.space.medium}} gap="medium" center>
|
|
<Layout.Container style={{userSelect: 'none'}}>
|
|
{targetMode.state === 'active' && (
|
|
<Typography.Text strong>Target mode: Select element</Typography.Text>
|
|
)}
|
|
{targetMode.state === 'disabled' && (
|
|
<Typography.Text strong>Interactive Visualizer</Typography.Text>
|
|
)}
|
|
{targetMode.state === 'selected' && (
|
|
<Slider
|
|
min={0}
|
|
tooltipVisible={false}
|
|
value={targetMode.sliderPosition}
|
|
max={targetMode.targetedNodes.length - 1}
|
|
onChange={(value) => {
|
|
setTargetMode(
|
|
produce(targetMode, (draft) => {
|
|
draft.sliderPosition = value;
|
|
}),
|
|
);
|
|
instance.uiActions.onSelectNode(
|
|
targetMode.targetedNodes[value],
|
|
'visualiser',
|
|
);
|
|
|
|
debouncedReportTargetAdjusted();
|
|
}}
|
|
/>
|
|
)}
|
|
</Layout.Container>
|
|
|
|
<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"
|
|
onClick={() => {
|
|
if (targetMode.state === 'disabled') {
|
|
setTargetMode({state: 'active'});
|
|
tracker.track('target-mode-switched', {on: true});
|
|
} else {
|
|
setTargetMode({state: 'disabled'});
|
|
tracker.track('target-mode-switched', {on: false});
|
|
}
|
|
}}
|
|
icon={
|
|
<AimOutlined
|
|
style={{
|
|
color:
|
|
targetMode.state === 'disabled'
|
|
? theme.black
|
|
: theme.primaryColor,
|
|
}}
|
|
/>
|
|
}
|
|
/>
|
|
</Tooltip>
|
|
<Tooltip title={focusToolTip}>
|
|
<Button
|
|
shape="circle"
|
|
disabled={focusDisabled}
|
|
onClick={() => {
|
|
if (focusedNode == null) {
|
|
instance.uiActions.onFocusNode(selectedNode?.id);
|
|
} else {
|
|
instance.uiActions.onFocusNode();
|
|
}
|
|
}}
|
|
icon={
|
|
focusedNode == null ? (
|
|
<FullscreenExitOutlined
|
|
style={{
|
|
color: theme.black,
|
|
}}
|
|
/>
|
|
) : (
|
|
<FullscreenOutlined
|
|
style={{
|
|
color: theme.primaryColor,
|
|
}}
|
|
/>
|
|
)
|
|
}
|
|
/>
|
|
</Tooltip>
|
|
</Layout.Horizontal>
|
|
</Layout.Right>
|
|
);
|
|
}
|
|
|
|
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);
|