Add import/export left rail menu

Summary: See D32311662 for details

Reviewed By: mweststrate

Differential Revision: D32316987

fbshipit-source-id: c2d173f981cce1b148f463d981977e23258ffc02
This commit is contained in:
Andrey Goncharov
2021-11-12 07:12:18 -08:00
committed by Facebook GitHub Bot
parent 32f722264f
commit 2591d1629e
4 changed files with 124 additions and 22 deletions

View File

@@ -376,7 +376,7 @@ function getTemplate(
{
label: 'Trigger deeplink...',
click() {
openDeeplinkDialog(store, logger);
openDeeplinkDialog(store);
},
},
{

View File

@@ -8,7 +8,7 @@
*/
import {Group, SUPPORTED_GROUPS} from './reducers/supportForm';
import {Logger} from 'flipper-common';
import {getLogger, Logger} from 'flipper-common';
import {Store} from './reducers/index';
import {importDataToStore} from './utils/exportData';
import {selectPlugin, getAllClients} from './reducers/connections';
@@ -150,13 +150,13 @@ export const uriComponents = (url: string): Array<string> => {
return [];
};
export function openDeeplinkDialog(store: Store, logger: Logger) {
export function openDeeplinkDialog(store: Store) {
Dialog.prompt({
title: 'Open deeplink',
message: 'Enter a deeplink:',
defaultValue: 'flipper://',
onConfirm: async (deeplink) => {
await handleDeeplink(store, logger, deeplink);
await handleDeeplink(store, getLogger(), deeplink);
return deeplink;
},
});

View File

@@ -8,7 +8,7 @@
*/
import React, {cloneElement, useState, useCallback, useMemo} from 'react';
import {Button, Divider, Badge, Tooltip, Avatar, Popover} from 'antd';
import {Button, Divider, Badge, Tooltip, Avatar, Popover, Menu} from 'antd';
import {
MobileFilled,
AppstoreOutlined,
@@ -20,6 +20,7 @@ import {
QuestionCircleOutlined,
MedicineBoxOutlined,
RocketOutlined,
SwapOutlined,
} from '@ant-design/icons';
import {SidebarLeft, SidebarRight} from './SandyIcons';
import {useDispatch, useStore} from '../utils/useStore';
@@ -27,7 +28,13 @@ import {
toggleLeftSidebarVisible,
toggleRightSidebarVisible,
} from '../reducers/application';
import {theme, Layout, withTrackingScope, Dialog} from 'flipper-plugin';
import {
theme,
Layout,
withTrackingScope,
Dialog,
useTrackedCallback,
} from 'flipper-plugin';
import SetupDoctorScreen, {checkHasNewProblem} from './SetupDoctorScreen';
import SettingsSheet from '../chrome/SettingsSheet';
import WelcomeScreen from './WelcomeScreen';
@@ -50,6 +57,17 @@ import FpsGraph from '../chrome/FpsGraph';
import UpdateIndicator from '../chrome/UpdateIndicator';
import PluginManager from '../chrome/plugin-manager/PluginManager';
import {showLoginDialog} from '../chrome/fb-stubs/SignInSheet';
import SubMenu from 'antd/lib/menu/SubMenu';
import constants from '../fb-stubs/constants';
import {
canFileExport,
canOpenDialog,
showOpenDialog,
startFileExport,
startLinkExport,
} from '../utils/exportData';
import {openDeeplinkDialog} from '../deeplink';
import {css} from '@emotion/css';
const LeftRailButtonElem = styled(Button)<{kind?: 'small'}>(({kind}) => ({
width: kind === 'small' ? 32 : 36,
@@ -76,7 +94,7 @@ export function LeftRailButton({
selected?: boolean;
disabled?: boolean;
count?: number | true;
title: string;
title?: string;
onClick?: React.MouseEventHandler<HTMLElement>;
}) {
let iconElement =
@@ -89,22 +107,31 @@ export function LeftRailButton({
<Badge count={count}>{iconElement}</Badge>
);
}
return (
<Tooltip title={title} placement="right">
<LeftRailButtonElem
title={title}
kind={small ? 'small' : undefined}
type={selected ? 'primary' : 'ghost'}
icon={iconElement}
onClick={onClick}
disabled={disabled}
style={{
color: toggled ? theme.primaryColor : undefined,
background: toggled ? theme.backgroundWash : undefined,
}}
/>
</Tooltip>
let res = (
<LeftRailButtonElem
title={title}
kind={small ? 'small' : undefined}
type={selected ? 'primary' : 'ghost'}
icon={iconElement}
onClick={onClick}
disabled={disabled}
style={{
color: toggled ? theme.primaryColor : undefined,
background: toggled ? theme.backgroundWash : undefined,
}}
/>
);
if (title) {
res = (
<Tooltip title={title} placement="right">
{res}
</Tooltip>
);
}
return res;
}
const LeftRailDivider = styled(Divider)({
@@ -163,6 +190,7 @@ export const LeftRail = withTrackingScope(function LeftRail({
<SupportFormButton />
<RightSidebarToggleButton />
<LeftSidebarToggleButton />
<ImportExportButton />
{config.showLogin && <LoginButton />}
</Layout.Container>
</Layout.Bottom>
@@ -170,6 +198,72 @@ export const LeftRail = withTrackingScope(function LeftRail({
);
});
const menu = css`
border: none;
`;
const submenu = css`
.ant-menu-submenu-title {
width: 32px;
height: 32px !important;
line-height: 32px !important;
padding: 0;
margin: 0;
}
.ant-menu-submenu-arrow {
display: none;
}
`;
function ImportExportButton() {
const store = useStore();
const startFileExportTracked = useTrackedCallback(
'File export',
() => startFileExport(store.dispatch),
[store.dispatch],
);
const startLinkExportTracked = useTrackedCallback(
'Link export',
() => startLinkExport(store.dispatch),
[store.dispatch],
);
const startImportTracked = useTrackedCallback(
'File import',
() => showOpenDialog(store),
[store],
);
return (
<Menu mode="vertical" className={menu}>
<SubMenu
popupOffset={[10, 0]}
key="importexport"
title={<LeftRailButton icon={<SwapOutlined />} small />}
className={submenu}>
{canFileExport() ? (
<Menu.Item key="exportFile" onClick={startFileExportTracked}>
Export file
</Menu.Item>
) : null}
{constants.ENABLE_SHAREABLE_LINK ? (
<Menu.Item key="exportShareableLink" onClick={startLinkExportTracked}>
Export shareable link
</Menu.Item>
) : null}
{canOpenDialog() ? (
<Menu.Item key="importFlipperFile" onClick={startImportTracked}>
Import Flipper file
</Menu.Item>
) : null}
<Menu.Item
key="triggerDeeplink"
onClick={() => openDeeplinkDialog(store)}>
Trigger deeplink
</Menu.Item>
</SubMenu>
</Menu>
);
}
function LeftSidebarToggleButton() {
const dispatch = useDispatch();
const mainMenuVisible = useStore(

View File

@@ -599,6 +599,10 @@ export const importFileToStore = (file: string, store: Store) => {
});
};
export function canOpenDialog() {
return !!getRenderHostInstance().showOpenDialog;
}
export function showOpenDialog(store: Store) {
return getRenderHostInstance()
.showOpenDialog?.({
@@ -613,6 +617,10 @@ export function showOpenDialog(store: Store) {
});
}
export function canFileExport() {
return !!getRenderHostInstance().showSaveDialog;
}
export async function startFileExport(dispatch: Store['dispatch']) {
const file = await getRenderHostInstance().showSaveDialog?.({
title: 'FlipperExport',