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:
committed by
Facebook GitHub Bot
parent
9b9f5d15a1
commit
ac24bbed3e
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user