Update context menu for new ant design api

Summary:
Mostly mechanical change from jsx to object based api. However some changes:

1. Managed to get rid of UIDebugger context menu item. its now possible to listen to when any context menu is clicked

2. The construction code is cleaner. no more mutable arrary and pushing, its just a big spliced literal

3. Had to change how the ide function worked. It is  dynamic and used react query hook to update the number of items. Added a callback to recreate this behaviour.

Reviewed By: aigoncharov

Differential Revision: D48910165

fbshipit-source-id: 9a71f5ecd302e6ff72194f83a13839f78e9b0796
This commit is contained in:
Luke De Feo
2023-09-04 02:19:53 -07:00
committed by Facebook GitHub Bot
parent 32ef1bd565
commit b336ed38fa
6 changed files with 160 additions and 197 deletions

View File

@@ -9,16 +9,16 @@
import {FrameworkEvent, Id, ClientNode} from '../../ClientTypes';
import {OnSelectNode, ViewMode} from '../../DesktopTypes';
import React, {ReactNode} from 'react';
import React, {useEffect, useState} from 'react';
import {DataSource, getFlipperLib} from 'flipper-plugin';
import {Dropdown, Menu} from 'antd';
import {UIDebuggerMenuItem} from '../util/UIDebuggerMenuItem';
import {Dropdown, MenuProps} from 'antd';
import {tracker} from '../../utils/tracker';
import {
BigGrepContextMenuItems,
IDEContextMenuItems,
bigGrepContextMenuItems,
ideContextMenuItems,
} from '../fb-stubs/IDEContextMenu';
import {
CopyFilled,
CopyOutlined,
FullscreenExitOutlined,
FullscreenOutlined,
@@ -28,6 +28,9 @@ import {
SnippetsOutlined,
TableOutlined,
} from '@ant-design/icons';
import {filterOutFalsy} from '../../utils/array';
type MenuItems = MenuProps['items'];
export const ContextMenu: React.FC<{
frameworkEvents: DataSource<FrameworkEvent>;
@@ -55,104 +58,29 @@ export const ContextMenu: React.FC<{
onCollapseNonAncestors,
onSelectNode,
}) => {
const copyItems: ReactNode[] = [];
const [_, setIdeItemsRerender] = useState(0);
const hoveredNode = nodes.get(hoveredNodeId ?? Number.MAX_SAFE_INTEGER);
let treeCollapseItems: ReactNode[] = [];
if (hoveredNode) {
treeCollapseItems = [
<UIDebuggerMenuItem
key="expand-recursive"
text="Expand recursively"
icon={<MenuUnfoldOutlined />}
onClick={() => {
onExpandRecursively(hoveredNode.id);
onSelectNode(hoveredNode.id, 'context-menu');
tracker.track('context-menu-expand-recursive', {});
}}
/>,
<UIDebuggerMenuItem
key="collapse-recursive"
text="Collapse recurisvely"
icon={<MenuFoldOutlined />}
onClick={() => {
onCollapseRecursively(hoveredNode.id);
onSelectNode(hoveredNode.id, 'context-menu');
tracker.track('context-menu-collapse-recursive', {});
}}
/>,
<UIDebuggerMenuItem
key="collapse-non-ancestors"
text="Collapse non ancestors"
icon={<NodeExpandOutlined />}
onClick={() => {
onCollapseNonAncestors(hoveredNode.id);
onSelectNode(hoveredNode.id, 'context-menu');
tracker.track('context-menu-collapse-non-ancestors', {});
}}
/>,
<Menu.Divider key="expand-divider" />,
];
copyItems.push(
<UIDebuggerMenuItem
key="Copy Element name"
text="Copy Element name"
icon={<CopyOutlined />}
onClick={() => {
tracker.track('context-menu-name-copied', {name: hoveredNode.name});
getFlipperLib().writeTextToClipboard(hoveredNode.name);
}}
/>,
);
copyItems.push(
Object.entries(hoveredNode.inlineAttributes).map(([key, value]) => (
<UIDebuggerMenuItem
key={key}
text={`Copy ${key}`}
icon={<SnippetsOutlined />}
onClick={() => {
tracker.track('context-menu-copied', {
name: hoveredNode.name,
key,
value,
});
getFlipperLib().writeTextToClipboard(value);
}}
/>
)),
);
copyItems.push(
<BigGrepContextMenuItems key="big-grep" node={hoveredNode} />,
);
}
const focus = hoveredNode != null &&
focusedNodeId !== hoveredNodeId &&
hoveredNode.bounds.height !== 0 &&
hoveredNode.bounds.width !== 0 && (
<UIDebuggerMenuItem
key="focus"
text={`Focus element`}
icon={<FullscreenExitOutlined />}
onClick={() => {
onFocusNode(hoveredNodeId);
}}
/>
);
hoveredNode.bounds.width !== 0 && {
key: 'focus',
label: `Focus element`,
icon: <FullscreenExitOutlined />,
onClick: () => {
onFocusNode(hoveredNodeId);
},
};
const removeFocus = focusedNodeId && (
<UIDebuggerMenuItem
key="remove-focus"
text="Remove focus"
icon={<FullscreenOutlined />}
onClick={() => {
onFocusNode(undefined);
}}
/>
);
const removeFocus = focusedNodeId && {
key: 'remove-focus',
label: 'Remove focus',
icon: <FullscreenOutlined />,
onClick: () => {
onFocusNode(undefined);
},
};
const matchingFrameworkEvents =
(hoveredNode &&
@@ -160,42 +88,100 @@ export const ContextMenu: React.FC<{
[];
const frameworkEventsTable = matchingFrameworkEvents.length > 0 &&
hoveredNode && (
<UIDebuggerMenuItem
text="Explore events"
onClick={() => {
onSetViewMode({
mode: 'frameworkEventsTable',
nodeId: hoveredNode.id,
isTree: hoveredNode.tags.includes('TreeRoot'),
});
}}
icon={<TableOutlined />}
/>
);
hoveredNode && {
key: 'events-table',
label: 'Explore events',
icon: <TableOutlined />,
onClick: () => {
onSetViewMode({
mode: 'frameworkEventsTable',
nodeId: hoveredNode.id,
isTree: hoveredNode.tags.includes('TreeRoot'),
});
},
};
const focusItems = [focus, removeFocus, frameworkEventsTable];
const items: MenuItems =
hoveredNode == null
? []
: filterOutFalsy([
{
key: 'expand-recursive',
label: 'Expand recursively',
icon: <MenuUnfoldOutlined />,
onClick: () => {
onExpandRecursively(hoveredNode.id);
onSelectNode(hoveredNode.id, 'context-menu');
tracker.track('context-menu-expand-recursive', {});
},
},
{
key: 'collapse-recursive',
label: 'Collapse recurisvely',
icon: <MenuFoldOutlined />,
onClick: () => {
onCollapseRecursively(hoveredNode.id);
onSelectNode(hoveredNode.id, 'context-menu');
tracker.track('context-menu-collapse-recursive', {});
},
},
{
key: 'collapse-non-ancestors',
label: 'Collapse non ancestors',
icon: <NodeExpandOutlined />,
onClick: () => {
onCollapseNonAncestors(hoveredNode.id);
onSelectNode(hoveredNode.id, 'context-menu');
tracker.track('context-menu-collapse-non-ancestors', {});
},
},
{type: 'divider'},
...focusItems,
focusItems.length > 0 && {type: 'divider'},
{
key: 'Copy Element name',
label: 'Copy Element name',
icon: <CopyOutlined />,
onClick: () => {
tracker.track('context-menu-name-copied', {
name: hoveredNode.name,
});
getFlipperLib().writeTextToClipboard(hoveredNode.name);
},
},
...Object.entries(hoveredNode.inlineAttributes).map(
([key, value]) => ({
key: key,
label: `Copy ${key}`,
icon: <SnippetsOutlined />,
onClick: () => {
tracker.track('context-menu-copied', {
name: hoveredNode.name,
key,
value,
});
getFlipperLib().writeTextToClipboard(value);
},
}),
),
...(bigGrepContextMenuItems(hoveredNode) || []),
...(ideContextMenuItems(hoveredNode, () =>
setIdeItemsRerender((value) => value + 1),
) || []),
]);
return (
<Dropdown
onVisibleChange={(visible) => {
onOpenChange={(visible) => {
onContextMenuOpen(visible);
}}
overlay={() => {
return (
<Menu>
{treeCollapseItems}
{focus}
{removeFocus}
{frameworkEventsTable}
{(focus || removeFocus || frameworkEventsTable) && (
<Menu.Divider key="divider-focus" />
)}
{copyItems}
{hoveredNode && (
<IDEContextMenuItems key="ide" node={hoveredNode} />
)}
</Menu>
);
menu={{
items,
onClick: () => {
onContextMenuOpen(false);
},
}}
trigger={['contextMenu']}>
{children}