From 2591d1629ec2c42c1b61cecc13bdf3ff41d14a40 Mon Sep 17 00:00:00 2001 From: Andrey Goncharov Date: Fri, 12 Nov 2021 07:12:18 -0800 Subject: [PATCH] Add import/export left rail menu Summary: See D32311662 for details Reviewed By: mweststrate Differential Revision: D32316987 fbshipit-source-id: c2d173f981cce1b148f463d981977e23258ffc02 --- desktop/app/src/MenuBar.tsx | 2 +- desktop/app/src/deeplink.tsx | 6 +- desktop/app/src/sandy-chrome/LeftRail.tsx | 130 +++++++++++++++++++--- desktop/app/src/utils/exportData.tsx | 8 ++ 4 files changed, 124 insertions(+), 22 deletions(-) diff --git a/desktop/app/src/MenuBar.tsx b/desktop/app/src/MenuBar.tsx index 62c3ef0c8..486c975c6 100644 --- a/desktop/app/src/MenuBar.tsx +++ b/desktop/app/src/MenuBar.tsx @@ -376,7 +376,7 @@ function getTemplate( { label: 'Trigger deeplink...', click() { - openDeeplinkDialog(store, logger); + openDeeplinkDialog(store); }, }, { diff --git a/desktop/app/src/deeplink.tsx b/desktop/app/src/deeplink.tsx index b2d083b18..5440ecbb0 100644 --- a/desktop/app/src/deeplink.tsx +++ b/desktop/app/src/deeplink.tsx @@ -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 => { 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; }, }); diff --git a/desktop/app/src/sandy-chrome/LeftRail.tsx b/desktop/app/src/sandy-chrome/LeftRail.tsx index 91c0d9eff..448363f56 100644 --- a/desktop/app/src/sandy-chrome/LeftRail.tsx +++ b/desktop/app/src/sandy-chrome/LeftRail.tsx @@ -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; }) { let iconElement = @@ -89,22 +107,31 @@ export function LeftRailButton({ {iconElement} ); } - return ( - - - + + let res = ( + ); + + if (title) { + res = ( + + {res} + + ); + } + + return res; } const LeftRailDivider = styled(Divider)({ @@ -163,6 +190,7 @@ export const LeftRail = withTrackingScope(function LeftRail({ + {config.showLogin && } @@ -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 ( + + } small />} + className={submenu}> + {canFileExport() ? ( + + Export file + + ) : null} + {constants.ENABLE_SHAREABLE_LINK ? ( + + Export shareable link + + ) : null} + {canOpenDialog() ? ( + + Import Flipper file + + ) : null} + openDeeplinkDialog(store)}> + Trigger deeplink + + + + ); +} + function LeftSidebarToggleButton() { const dispatch = useDispatch(); const mainMenuVisible = useStore( diff --git a/desktop/app/src/utils/exportData.tsx b/desktop/app/src/utils/exportData.tsx index 406fba042..0f5ca3fe9 100644 --- a/desktop/app/src/utils/exportData.tsx +++ b/desktop/app/src/utils/exportData.tsx @@ -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',