Remove usage of Electron context menus
Summary: Removed the usage of electron's native context menus, and replaces it with Antd based context menu's. Reviewed By: passy Differential Revision: D31990756 fbshipit-source-id: 0312cbac5fd20a1a30603ce1058c03f4291b23b1
This commit is contained in:
committed by
Facebook GitHub Bot
parent
25590e14b9
commit
64e791e253
@@ -35,6 +35,7 @@ import {textContent} from 'flipper-plugin';
|
|||||||
import createPaste from './fb-stubs/createPaste';
|
import createPaste from './fb-stubs/createPaste';
|
||||||
import {getPluginTitle} from './utils/pluginUtils';
|
import {getPluginTitle} from './utils/pluginUtils';
|
||||||
import {getFlipperLib} from 'flipper-plugin';
|
import {getFlipperLib} from 'flipper-plugin';
|
||||||
|
import {ContextMenuItem} from './ui/components/ContextMenu';
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
onClear: () => void;
|
onClear: () => void;
|
||||||
@@ -421,7 +422,7 @@ class NotificationItem extends Component<
|
|||||||
> {
|
> {
|
||||||
constructor(props: ItemProps & PluginNotification) {
|
constructor(props: ItemProps & PluginNotification) {
|
||||||
super(props);
|
super(props);
|
||||||
const items: Array<Electron.MenuItemConstructorOptions> = [];
|
const items: Array<ContextMenuItem> = [];
|
||||||
if (props.onHidePlugin && props.plugin) {
|
if (props.onHidePlugin && props.plugin) {
|
||||||
items.push({
|
items.push({
|
||||||
label: `Hide ${getPluginTitle(props.plugin)} plugin`,
|
label: `Hide ${getPluginTitle(props.plugin)} plugin`,
|
||||||
@@ -444,7 +445,7 @@ class NotificationItem extends Component<
|
|||||||
}
|
}
|
||||||
|
|
||||||
state = {reportedNotHelpful: false};
|
state = {reportedNotHelpful: false};
|
||||||
contextMenuItems: Array<Electron.MenuItemConstructorOptions>;
|
contextMenuItems: Array<ContextMenuItem>;
|
||||||
deepLinkButton = React.createRef();
|
deepLinkButton = React.createRef();
|
||||||
|
|
||||||
createPaste = () => {
|
createPaste = () => {
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ exports[`load PluginInstaller list 1`] = `
|
|||||||
tabindex="0"
|
tabindex="0"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="css-18abd42-View-FlexBox-FlexColumn ecr18to0"
|
class="ant-dropdown-trigger css-18abd42-View-FlexBox-FlexColumn ecr18to0"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="css-1otvu18-View-FlexBox-FlexRow-TableHeadContainer ejga3101"
|
class="css-1otvu18-View-FlexBox-FlexRow-TableHeadContainer ejga3101"
|
||||||
@@ -132,7 +132,7 @@ exports[`load PluginInstaller list 1`] = `
|
|||||||
class="css-p5h61d-View-FlexBox-FlexColumn-Container esta8x30"
|
class="css-p5h61d-View-FlexBox-FlexColumn-Container esta8x30"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="css-18abd42-View-FlexBox-FlexColumn ecr18to0"
|
class="ant-dropdown-trigger css-18abd42-View-FlexBox-FlexColumn ecr18to0"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="css-hg3ptm-View-FlexBox-FlexRow-TableBodyRowContainer ehuguum1"
|
class="css-hg3ptm-View-FlexBox-FlexRow-TableBodyRowContainer ehuguum1"
|
||||||
@@ -391,7 +391,7 @@ exports[`load PluginInstaller list with one plugin installed 1`] = `
|
|||||||
tabindex="0"
|
tabindex="0"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="css-18abd42-View-FlexBox-FlexColumn ecr18to0"
|
class="ant-dropdown-trigger css-18abd42-View-FlexBox-FlexColumn ecr18to0"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="css-1otvu18-View-FlexBox-FlexRow-TableHeadContainer ejga3101"
|
class="css-1otvu18-View-FlexBox-FlexRow-TableHeadContainer ejga3101"
|
||||||
@@ -466,7 +466,7 @@ exports[`load PluginInstaller list with one plugin installed 1`] = `
|
|||||||
class="css-p5h61d-View-FlexBox-FlexColumn-Container esta8x30"
|
class="css-p5h61d-View-FlexBox-FlexColumn-Container esta8x30"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="css-18abd42-View-FlexBox-FlexColumn ecr18to0"
|
class="ant-dropdown-trigger css-18abd42-View-FlexBox-FlexColumn ecr18to0"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="css-hg3ptm-View-FlexBox-FlexRow-TableBodyRowContainer ehuguum1"
|
class="css-hg3ptm-View-FlexBox-FlexRow-TableBodyRowContainer ehuguum1"
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
import {Provider} from 'react-redux';
|
import {Provider} from 'react-redux';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
|
|
||||||
import ContextMenuProvider from './ui/components/ContextMenuProvider';
|
|
||||||
import GK from './fb-stubs/GK';
|
import GK from './fb-stubs/GK';
|
||||||
import {init as initLogger} from './fb-stubs/Logger';
|
import {init as initLogger} from './fb-stubs/Logger';
|
||||||
import {SandyApp} from './sandy-chrome/SandyApp';
|
import {SandyApp} from './sandy-chrome/SandyApp';
|
||||||
@@ -137,11 +136,9 @@ class AppFrame extends React.Component<
|
|||||||
<PersistGate persistor={persistor}>
|
<PersistGate persistor={persistor}>
|
||||||
<CacheProvider value={cache}>
|
<CacheProvider value={cache}>
|
||||||
<TooltipProvider>
|
<TooltipProvider>
|
||||||
<ContextMenuProvider>
|
<_NuxManagerContext.Provider value={_createNuxManager()}>
|
||||||
<_NuxManagerContext.Provider value={_createNuxManager()}>
|
<SandyApp />
|
||||||
<SandyApp />
|
</_NuxManagerContext.Provider>
|
||||||
</_NuxManagerContext.Provider>
|
|
||||||
</ContextMenuProvider>
|
|
||||||
</TooltipProvider>
|
</TooltipProvider>
|
||||||
</CacheProvider>
|
</CacheProvider>
|
||||||
</PersistGate>
|
</PersistGate>
|
||||||
|
|||||||
@@ -148,48 +148,50 @@ export function SandyApp() {
|
|||||||
) : null;
|
) : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout.Bottom>
|
<RootElement>
|
||||||
<Layout.Left>
|
<Layout.Bottom>
|
||||||
<Layout.Horizontal>
|
<Layout.Left>
|
||||||
<LeftRail
|
<Layout.Horizontal>
|
||||||
toplevelSelection={toplevelSelection}
|
<LeftRail
|
||||||
setToplevelSelection={setToplevelSelection}
|
toplevelSelection={toplevelSelection}
|
||||||
/>
|
setToplevelSelection={setToplevelSelection}
|
||||||
<_Sidebar width={250} minWidth={220} maxWidth={800} gutter>
|
/>
|
||||||
{leftMenuContent && (
|
<_Sidebar width={250} minWidth={220} maxWidth={800} gutter>
|
||||||
<TrackingScope scope={toplevelSelection!}>
|
{leftMenuContent && (
|
||||||
{leftMenuContent}
|
<TrackingScope scope={toplevelSelection!}>
|
||||||
</TrackingScope>
|
{leftMenuContent}
|
||||||
)}
|
</TrackingScope>
|
||||||
</_Sidebar>
|
|
||||||
</Layout.Horizontal>
|
|
||||||
<MainContainer>
|
|
||||||
{staticView ? (
|
|
||||||
<TrackingScope
|
|
||||||
scope={
|
|
||||||
(staticView as any).displayName ??
|
|
||||||
staticView.name ??
|
|
||||||
staticView.constructor?.name ??
|
|
||||||
'unknown static view'
|
|
||||||
}>
|
|
||||||
{staticView === WelcomeScreenStaticView ? (
|
|
||||||
React.createElement(staticView) /* avoid shadow */
|
|
||||||
) : (
|
|
||||||
<ContentContainer>
|
|
||||||
{React.createElement(staticView, {
|
|
||||||
logger: logger,
|
|
||||||
})}
|
|
||||||
</ContentContainer>
|
|
||||||
)}
|
)}
|
||||||
</TrackingScope>
|
</_Sidebar>
|
||||||
) : (
|
</Layout.Horizontal>
|
||||||
<PluginContainer logger={logger} />
|
<MainContainer>
|
||||||
)}
|
{staticView ? (
|
||||||
{outOfContentsContainer}
|
<TrackingScope
|
||||||
</MainContainer>
|
scope={
|
||||||
</Layout.Left>
|
(staticView as any).displayName ??
|
||||||
<_PortalsManager />
|
staticView.name ??
|
||||||
</Layout.Bottom>
|
staticView.constructor?.name ??
|
||||||
|
'unknown static view'
|
||||||
|
}>
|
||||||
|
{staticView === WelcomeScreenStaticView ? (
|
||||||
|
React.createElement(staticView) /* avoid shadow */
|
||||||
|
) : (
|
||||||
|
<ContentContainer>
|
||||||
|
{React.createElement(staticView, {
|
||||||
|
logger: logger,
|
||||||
|
})}
|
||||||
|
</ContentContainer>
|
||||||
|
)}
|
||||||
|
</TrackingScope>
|
||||||
|
) : (
|
||||||
|
<PluginContainer logger={logger} />
|
||||||
|
)}
|
||||||
|
{outOfContentsContainer}
|
||||||
|
</MainContainer>
|
||||||
|
</Layout.Left>
|
||||||
|
<_PortalsManager />
|
||||||
|
</Layout.Bottom>
|
||||||
|
</RootElement>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,6 +222,12 @@ const MainContainer = styled(Layout.Container)({
|
|||||||
padding: `${theme.space.large}px ${theme.space.large}px ${theme.space.large}px 0`,
|
padding: `${theme.space.large}px ${theme.space.large}px ${theme.space.large}px 0`,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const RootElement = styled.div({
|
||||||
|
display: 'flex',
|
||||||
|
height: '100%',
|
||||||
|
});
|
||||||
|
RootElement.displayName = 'SandyAppRootElement';
|
||||||
|
|
||||||
function registerStartupTime(logger: Logger) {
|
function registerStartupTime(logger: Logger) {
|
||||||
// track time since launch
|
// track time since launch
|
||||||
const [s, ns] = process.hrtime();
|
const [s, ns] = process.hrtime();
|
||||||
|
|||||||
@@ -7,19 +7,30 @@
|
|||||||
* @format
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import * as React from 'react';
|
||||||
createElement,
|
import {Menu, Dropdown} from 'antd';
|
||||||
useContext,
|
import {createElement, useCallback, forwardRef, Ref, ReactElement} from 'react';
|
||||||
useCallback,
|
|
||||||
forwardRef,
|
|
||||||
Ref,
|
|
||||||
ReactElement,
|
|
||||||
} from 'react';
|
|
||||||
import {ContextMenuContext} from './ContextMenuProvider';
|
|
||||||
import FlexColumn from './FlexColumn';
|
import FlexColumn from './FlexColumn';
|
||||||
import {MenuItemConstructorOptions} from 'electron';
|
import {CheckOutlined} from '@ant-design/icons';
|
||||||
|
|
||||||
export type MenuTemplate = Array<MenuItemConstructorOptions>;
|
export type ContextMenuItem =
|
||||||
|
| {
|
||||||
|
readonly label: string;
|
||||||
|
readonly click?: () => void;
|
||||||
|
readonly role?: string;
|
||||||
|
readonly enabled?: boolean;
|
||||||
|
readonly type?: 'normal' | 'checkbox';
|
||||||
|
readonly checked?: boolean;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
readonly type: 'separator';
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
readonly label: string;
|
||||||
|
readonly submenu: MenuTemplate;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type MenuTemplate = ReadonlyArray<ContextMenuItem>;
|
||||||
|
|
||||||
type Props<C> = {
|
type Props<C> = {
|
||||||
/** List of items in the context menu. Used for static menus. */
|
/** List of items in the context menu. Used for static menus. */
|
||||||
@@ -33,6 +44,8 @@ type Props<C> = {
|
|||||||
onMouseDown?: (e: React.MouseEvent) => any;
|
onMouseDown?: (e: React.MouseEvent) => any;
|
||||||
} & C;
|
} & C;
|
||||||
|
|
||||||
|
const contextMenuTrigger = ['contextMenu' as const];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Native context menu that is shown on secondary click.
|
* Native context menu that is shown on secondary click.
|
||||||
* Uses [Electron's context menu API](https://electronjs.org/docs/api/menu-item)
|
* Uses [Electron's context menu API](https://electronjs.org/docs/api/menu-item)
|
||||||
@@ -45,21 +58,53 @@ export default forwardRef(function ContextMenu<C>(
|
|||||||
{items, buildItems, component, children, ...otherProps}: Props<C>,
|
{items, buildItems, component, children, ...otherProps}: Props<C>,
|
||||||
ref: Ref<any> | null,
|
ref: Ref<any> | null,
|
||||||
) {
|
) {
|
||||||
const contextMenuManager = useContext(ContextMenuContext);
|
|
||||||
const onContextMenu = useCallback(() => {
|
const onContextMenu = useCallback(() => {
|
||||||
if (items != null) {
|
return createContextMenu(items ?? buildItems?.() ?? []);
|
||||||
contextMenuManager?.appendToContextMenu(items);
|
|
||||||
} else if (buildItems != null) {
|
|
||||||
contextMenuManager?.appendToContextMenu(buildItems());
|
|
||||||
}
|
|
||||||
}, [items, buildItems]);
|
}, [items, buildItems]);
|
||||||
return createElement(
|
|
||||||
component || FlexColumn,
|
return (
|
||||||
{
|
<Dropdown overlay={onContextMenu} trigger={contextMenuTrigger}>
|
||||||
ref,
|
{createElement(
|
||||||
onContextMenu,
|
component || FlexColumn,
|
||||||
...otherProps,
|
{
|
||||||
},
|
ref,
|
||||||
children,
|
...otherProps,
|
||||||
|
},
|
||||||
|
children,
|
||||||
|
)}
|
||||||
|
</Dropdown>
|
||||||
);
|
);
|
||||||
}) as <T>(p: Props<T> & {ref?: Ref<any>}) => ReactElement;
|
}) as <T>(p: Props<T> & {ref?: Ref<any>}) => ReactElement;
|
||||||
|
|
||||||
|
export function createContextMenu(items: MenuTemplate) {
|
||||||
|
return <Menu>{items.map(createMenuItem)}</Menu>;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createMenuItem(item: ContextMenuItem, idx: number) {
|
||||||
|
if ('type' in item && item.type === 'separator') {
|
||||||
|
return <Menu.Divider key={idx} />;
|
||||||
|
} else if ('submenu' in item) {
|
||||||
|
return (
|
||||||
|
<Menu.SubMenu key={idx} title={item.label}>
|
||||||
|
{item.submenu.map(createMenuItem)}
|
||||||
|
</Menu.SubMenu>
|
||||||
|
);
|
||||||
|
} else if ('label' in item) {
|
||||||
|
return (
|
||||||
|
<Menu.Item
|
||||||
|
key={idx}
|
||||||
|
onClick={item.click}
|
||||||
|
disabled={item.enabled === false}
|
||||||
|
role={item.role}
|
||||||
|
icon={
|
||||||
|
item.type === 'checkbox' ? (
|
||||||
|
<CheckOutlined
|
||||||
|
style={{visibility: item.checked ? 'visible' : 'hidden'}}
|
||||||
|
/>
|
||||||
|
) : undefined
|
||||||
|
}>
|
||||||
|
{item.label}
|
||||||
|
</Menu.Item>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,58 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) Facebook, Inc. and its 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 styled from '@emotion/styled';
|
|
||||||
import electron, {MenuItemConstructorOptions} from 'electron';
|
|
||||||
import React, {useRef, memo, createContext, useMemo, useCallback} from 'react';
|
|
||||||
|
|
||||||
type MenuTemplate = Array<MenuItemConstructorOptions>;
|
|
||||||
interface ContextMenuManager {
|
|
||||||
appendToContextMenu(items: MenuTemplate): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Container = styled.div({
|
|
||||||
display: 'flex',
|
|
||||||
height: '100%',
|
|
||||||
});
|
|
||||||
Container.displayName = 'ContextMenuProvider:Container';
|
|
||||||
|
|
||||||
export const ContextMenuContext = createContext<ContextMenuManager | undefined>(
|
|
||||||
undefined,
|
|
||||||
);
|
|
||||||
/**
|
|
||||||
* Flipper's root is already wrapped with this component, so plugins should not
|
|
||||||
* need to use this. ContextMenu is what you probably want to use.
|
|
||||||
* @deprecated use https://ant.design/components/dropdown/#components-dropdown-demo-context-menu
|
|
||||||
*/
|
|
||||||
const ContextMenuProvider: React.FC<{}> = memo(function ContextMenuProvider({
|
|
||||||
children,
|
|
||||||
}) {
|
|
||||||
const menuTemplate = useRef<MenuTemplate>([]);
|
|
||||||
const contextMenuManager = useMemo(
|
|
||||||
() => ({
|
|
||||||
appendToContextMenu(items: MenuTemplate) {
|
|
||||||
menuTemplate.current = menuTemplate.current.concat(items);
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
const onContextMenu = useCallback(() => {
|
|
||||||
const menu = electron.remote.Menu.buildFromTemplate(menuTemplate.current);
|
|
||||||
menuTemplate.current = [];
|
|
||||||
menu.popup({window: electron.remote.getCurrentWindow()});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ContextMenuContext.Provider value={contextMenuManager}>
|
|
||||||
<Container onContextMenu={onContextMenu}>{children}</Container>
|
|
||||||
</ContextMenuContext.Provider>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
export default ContextMenuProvider;
|
|
||||||
@@ -11,24 +11,22 @@ import {Filter} from '../filter/types';
|
|||||||
import {PureComponent} from 'react';
|
import {PureComponent} from 'react';
|
||||||
import Text from '../Text';
|
import Text from '../Text';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import electron, {MenuItemConstructorOptions} from 'electron';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {Property} from 'csstype';
|
import {Property} from 'csstype';
|
||||||
import {theme} from 'flipper-plugin';
|
import {theme} from 'flipper-plugin';
|
||||||
|
import {ContextMenuItem, createContextMenu} from '../ContextMenu';
|
||||||
|
import {Dropdown} from 'antd';
|
||||||
|
|
||||||
const Token = styled(Text)<{focused?: boolean; color?: Property.Color}>(
|
const Token = styled(Text)<{focused?: boolean; color?: Property.Color}>(
|
||||||
(props) => ({
|
(props) => ({
|
||||||
display: 'inline-flex',
|
display: 'inline-flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
backgroundColor: props.focused
|
backgroundColor: props.color || theme.buttonDefaultBackground,
|
||||||
? theme.textColorActive
|
|
||||||
: props.color || theme.buttonDefaultBackground,
|
|
||||||
borderRadius: 4,
|
borderRadius: 4,
|
||||||
marginRight: 4,
|
marginRight: 4,
|
||||||
padding: 4,
|
padding: 4,
|
||||||
paddingLeft: 6,
|
paddingLeft: 6,
|
||||||
height: 21,
|
height: 21,
|
||||||
color: props.focused ? 'white' : 'inherit',
|
|
||||||
'&:active': {
|
'&:active': {
|
||||||
backgroundColor: theme.textColorActive,
|
backgroundColor: theme.textColorActive,
|
||||||
color: theme.textColorPrimary,
|
color: theme.textColorPrimary,
|
||||||
@@ -103,8 +101,6 @@ type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default class FilterToken extends PureComponent<Props> {
|
export default class FilterToken extends PureComponent<Props> {
|
||||||
_ref?: Element | null;
|
|
||||||
|
|
||||||
onMouseDown = () => {
|
onMouseDown = () => {
|
||||||
if (
|
if (
|
||||||
this.props.filter.type !== 'enum' ||
|
this.props.filter.type !== 'enum' ||
|
||||||
@@ -117,7 +113,7 @@ export default class FilterToken extends PureComponent<Props> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
showDetails = () => {
|
showDetails = () => {
|
||||||
const menuTemplate: Array<MenuItemConstructorOptions> = [];
|
const menuTemplate: Array<ContextMenuItem> = [];
|
||||||
|
|
||||||
if (this.props.filter.type === 'enum') {
|
if (this.props.filter.type === 'enum') {
|
||||||
menuTemplate.push(
|
menuTemplate.push(
|
||||||
@@ -155,19 +151,7 @@ export default class FilterToken extends PureComponent<Props> {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const menu = electron.remote.Menu.buildFromTemplate(menuTemplate);
|
return createContextMenu(menuTemplate);
|
||||||
if (this._ref) {
|
|
||||||
const {bottom, left} = this._ref.getBoundingClientRect();
|
|
||||||
|
|
||||||
menu.popup({
|
|
||||||
window: electron.remote.getCurrentWindow(),
|
|
||||||
// @ts-ignore: async is private API
|
|
||||||
async: true,
|
|
||||||
// Note: Electron requires the x/y parameters to be integer values for marshalling
|
|
||||||
x: Math.round(left),
|
|
||||||
y: Math.round(bottom + 8),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
toggleFilter = () => {
|
toggleFilter = () => {
|
||||||
@@ -202,10 +186,6 @@ export default class FilterToken extends PureComponent<Props> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
setRef = (ref: HTMLSpanElement | null) => {
|
|
||||||
this._ref = ref;
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {filter} = this.props;
|
const {filter} = this.props;
|
||||||
let color;
|
let color;
|
||||||
@@ -231,21 +211,24 @@ export default class FilterToken extends PureComponent<Props> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Token
|
<Dropdown trigger={dropdownTrigger} overlay={this.showDetails}>
|
||||||
key={`${filter.key}:${value}=${filter.type}`}
|
<Token
|
||||||
tabIndex={-1}
|
key={`${filter.key}:${value}=${filter.type}`}
|
||||||
onMouseDown={this.onMouseDown}
|
tabIndex={-1}
|
||||||
focused={this.props.focused}
|
onMouseDown={this.onMouseDown}
|
||||||
color={color}
|
focused={this.props.focused}
|
||||||
ref={this.setRef}>
|
color={color}>
|
||||||
<Key type={this.props.filter.type} focused={this.props.focused}>
|
<Key type={this.props.filter.type} focused={this.props.focused}>
|
||||||
{filter.key}
|
{filter.key}
|
||||||
</Key>
|
</Key>
|
||||||
<Value>{value}</Value>
|
<Value>{value}</Value>
|
||||||
<Chevron tabIndex={-1} focused={this.props.focused}>
|
<Chevron tabIndex={-1} focused={this.props.focused}>
|
||||||
⌄
|
⌄
|
||||||
</Chevron>
|
</Chevron>
|
||||||
</Token>
|
</Token>
|
||||||
|
</Dropdown>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const dropdownTrigger = ['click' as const];
|
||||||
|
|||||||
@@ -17,12 +17,11 @@ import {
|
|||||||
TableBodyRow,
|
TableBodyRow,
|
||||||
TableOnAddFilter,
|
TableOnAddFilter,
|
||||||
} from './types';
|
} from './types';
|
||||||
import {MenuTemplate} from '../ContextMenu';
|
import {ContextMenuItem, MenuTemplate} from '../ContextMenu';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import AutoSizer from 'react-virtualized-auto-sizer';
|
import AutoSizer from 'react-virtualized-auto-sizer';
|
||||||
import {VariableSizeList as List} from 'react-window';
|
import {VariableSizeList as List} from 'react-window';
|
||||||
import {MenuItemConstructorOptions} from 'electron';
|
|
||||||
import TableHead from './TableHead';
|
import TableHead from './TableHead';
|
||||||
import TableRow from './TableRow';
|
import TableRow from './TableRow';
|
||||||
import ContextMenu from '../ContextMenu';
|
import ContextMenu from '../ContextMenu';
|
||||||
@@ -523,7 +522,7 @@ export class ManagedTable extends React.Component<
|
|||||||
getFlipperLib().writeTextToClipboard(cellText);
|
getFlipperLib().writeTextToClipboard(cellText);
|
||||||
};
|
};
|
||||||
|
|
||||||
buildContextMenuItems: () => Array<MenuItemConstructorOptions> = () => {
|
buildContextMenuItems: () => Array<ContextMenuItem> = () => {
|
||||||
const {highlightedRows} = this.state;
|
const {highlightedRows} = this.state;
|
||||||
if (highlightedRows.size === 0) {
|
if (highlightedRows.size === 0) {
|
||||||
return [];
|
return [];
|
||||||
|
|||||||
@@ -17,13 +17,12 @@ import {
|
|||||||
} from './types';
|
} from './types';
|
||||||
import {normalizeColumnWidth, isPercentage} from './utils';
|
import {normalizeColumnWidth, isPercentage} from './utils';
|
||||||
import {PureComponent} from 'react';
|
import {PureComponent} from 'react';
|
||||||
import ContextMenu from '../ContextMenu';
|
import ContextMenu, {ContextMenuItem} from '../ContextMenu';
|
||||||
import {theme, _Interactive, _InteractiveProps} from 'flipper-plugin';
|
import {theme, _Interactive, _InteractiveProps} from 'flipper-plugin';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import {colors} from '../colors';
|
import {colors} from '../colors';
|
||||||
import FlexRow from '../FlexRow';
|
import FlexRow from '../FlexRow';
|
||||||
import invariant from 'invariant';
|
import invariant from 'invariant';
|
||||||
import {MenuItemConstructorOptions} from 'electron';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
const TableHeaderArrow = styled.span({
|
const TableHeaderArrow = styled.span({
|
||||||
@@ -208,7 +207,7 @@ export default class TableHead extends PureComponent<{
|
|||||||
onColumnResize?: TableOnColumnResize;
|
onColumnResize?: TableOnColumnResize;
|
||||||
horizontallyScrollable?: boolean;
|
horizontallyScrollable?: boolean;
|
||||||
}> {
|
}> {
|
||||||
buildContextMenu = (): MenuItemConstructorOptions[] => {
|
buildContextMenu = (): ContextMenuItem[] => {
|
||||||
const visibles = this.props.columnOrder
|
const visibles = this.props.columnOrder
|
||||||
.map((c) => (c.visible ? c.key : null))
|
.map((c) => (c.visible ? c.key : null))
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
|
|||||||
@@ -60,7 +60,6 @@ export {default as Orderable} from './components/Orderable';
|
|||||||
export {Component, PureComponent} from 'react';
|
export {Component, PureComponent} from 'react';
|
||||||
|
|
||||||
// context menus and dropdowns
|
// context menus and dropdowns
|
||||||
export {default as ContextMenuProvider} from './components/ContextMenuProvider';
|
|
||||||
export {default as ContextMenu} from './components/ContextMenu';
|
export {default as ContextMenu} from './components/ContextMenu';
|
||||||
|
|
||||||
// file
|
// file
|
||||||
|
|||||||
@@ -8,8 +8,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
// eslint-disable-next-line
|
|
||||||
import electron, {OpenDialogOptions, remote} from 'electron';
|
|
||||||
import {Atom, DataTableManager, getFlipperLib} from 'flipper-plugin';
|
import {Atom, DataTableManager, getFlipperLib} from 'flipper-plugin';
|
||||||
import {createContext} from 'react';
|
import {createContext} from 'react';
|
||||||
import {Header, Request} from '../types';
|
import {Header, Request} from '../types';
|
||||||
|
|||||||
Reference in New Issue
Block a user