Don't use Electron menus for dropdowns

Summary: A bunch of dropdowns in Flipper are using native context menu to show their items. Rewrote to use Antd instead and reduce coupling with Electron

Reviewed By: timur-valiev

Differential Revision: D29694035

fbshipit-source-id: 5fd80c255c308567daf3e46e03bc27494c8ba142
This commit is contained in:
Michel Weststrate
2021-07-15 01:51:58 -07:00
committed by Facebook GitHub Bot
parent 9b9f5d15a1
commit ac24bbed3e
2 changed files with 31 additions and 81 deletions

View File

@@ -8,15 +8,17 @@
*/
import {useMemo} from 'react';
import {Button, Layout} from '../ui';
import React from 'react';
import {Console, Hook} from 'console-feed';
import type {Methods} from 'console-feed/lib/definitions/Methods';
import type {Styles} from 'console-feed/lib/definitions/Styles';
import {createState, useValue} from 'flipper-plugin';
import {useLocalStorageState} from 'flipper-plugin';
import {theme, Toolbar} from 'flipper-plugin';
import {theme, Toolbar, Layout} from 'flipper-plugin';
import {useIsDarkMode} from '../utils/useIsDarkMode';
import {Button, Dropdown, Menu, Checkbox} from 'antd';
import {DownOutlined} from '@ant-design/icons';
import {DeleteOutlined} from '@ant-design/icons';
const MAX_LOG_ITEMS = 1000;
@@ -71,32 +73,37 @@ export function ConsoleLogs() {
defaultLogLevels,
);
const dropdown = useMemo(() => {
return allLogLevels.map(
(l): Electron.MenuItemConstructorOptions => ({
label: l,
checked: logLevels.includes(l),
type: 'checkbox',
click() {
setLogLevels((state) =>
state.includes(l)
? state.filter((level) => level !== l)
: [l, ...state],
);
},
}),
);
}, [logLevels, setLogLevels]);
const styles = useMemo(buildTheme, []);
return (
<Layout.Top>
<Toolbar wash>
<Button onClick={clearLogs} icon="trash">
<Button onClick={clearLogs} icon={<DeleteOutlined />}>
Clear Logs
</Button>
<Button dropdown={dropdown}>Log Levels</Button>
<Dropdown
overlay={
<Menu>
{allLogLevels.map((l) => (
<Menu.Item
key={l}
onClick={() => {
setLogLevels((state) =>
state.includes(l)
? state.filter((level) => level !== l)
: [l, ...state],
);
}}>
<Checkbox checked={logLevels.includes(l)}>{l}</Checkbox>
</Menu.Item>
))}
</Menu>
}>
<Button>
Log Levels
<DownOutlined />
</Button>
</Dropdown>
</Toolbar>
<Layout.ScrollContainer vertical>
<Console

View File

@@ -7,14 +7,12 @@
* @format
*/
import React, {useState, useCallback, useMemo} from 'react';
import {MenuItemConstructorOptions} from 'electron';
import React, {useCallback} from 'react';
import styled from '@emotion/styled';
import {Button as AntdButton, Dropdown, Menu} from 'antd';
import {Button as AntdButton} from 'antd';
import Glyph, {IconSize} from './Glyph';
import type {ButtonProps} from 'antd/lib/button';
import {DownOutlined, CheckOutlined} from '@ant-design/icons';
import {theme, getFlipperLib} from 'flipper-plugin';
type ButtonType = 'primary' | 'success' | 'warning' | 'danger';
@@ -53,10 +51,6 @@ type Props = {
* Children.
*/
children?: React.ReactNode;
/**
* Dropdown menu template shown on click.
*/
dropdown?: Array<MenuItemConstructorOptions>;
/**
* Name of the icon dispalyed next to the text
*/
@@ -109,14 +103,11 @@ function SandyButton({
children,
iconSize,
iconVariant,
dropdown,
type,
onClick,
href,
...restProps
}: Props) {
const [dropdownVisible, setDropdownVible] = useState(false);
const handleClick = useCallback(
(e: React.MouseEvent) => {
if (disabled === true) {
@@ -129,9 +120,6 @@ function SandyButton({
},
[disabled, onClick, href],
);
const handleVisibleChange = useCallback((flag: boolean) => {
setDropdownVible(flag);
}, []);
let iconComponent;
if (icon != null) {
iconComponent = (
@@ -145,39 +133,7 @@ function SandyButton({
);
}
const dropdownItems = useMemo(
() =>
dropdown && (
<Menu>
{dropdown!.map((item, idx) => (
<Menu.Item
onClick={(e) => {
// @ts-ignore this event args are bound to electron, remove in the future
item.click(item);
if (item.checked !== undefined) {
// keep the menu item for check lists
e.domEvent.stopPropagation();
e.domEvent.preventDefault();
}
}}
disabled={item.enabled === false}
icon={
item.checked !== undefined && (
<CheckOutlined
style={{visibility: item.checked ? 'visible' : 'hidden'}}
/>
)
}
key={idx}>
{item.label}
</Menu.Item>
))}
</Menu>
),
[dropdown],
);
const button = (
return (
<AntdButton
/* Probably more properties need passing on, but lets be explicit about it */
style={restProps.style}
@@ -187,19 +143,6 @@ function SandyButton({
onClick={handleClick}
icon={iconComponent}>
{children}
{dropdown ? <DownOutlined /> : null}
</AntdButton>
);
if (dropdown) {
return (
<Dropdown
overlay={dropdownItems!}
visible={dropdownVisible}
onVisibleChange={handleVisibleChange}>
{button}
</Dropdown>
);
} else {
return button;
}
}