Device plugin list
Summary: Render a plugin list Will add tests once the entire feature is complete Reviewed By: cekkaewnumchai Differential Revision: D24079897 fbshipit-source-id: db7250ff612b67ab18dfcacdcb9c44dab596933d
This commit is contained in:
committed by
Facebook GitHub Bot
parent
c38a4413dc
commit
f14a724fa5
@@ -16,7 +16,7 @@ import {InfoCircleOutlined} from '@ant-design/icons';
|
||||
|
||||
export const LeftSidebar: React.FC = ({children}) => (
|
||||
<Layout.Container borderRight padv="small">
|
||||
<Layout.Vertical>{children}</Layout.Vertical>
|
||||
{children}
|
||||
</Layout.Container>
|
||||
);
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ import {Logger} from '../fb-interfaces/Logger';
|
||||
|
||||
import {LeftRail} from './LeftRail';
|
||||
import {TemporarilyTitlebar} from './TemporarilyTitlebar';
|
||||
import SandyDesignSystem from './SandyDesignSystem';
|
||||
import {registerStartupTime} from '../App';
|
||||
import {useStore, useDispatch} from '../utils/useStore';
|
||||
import {SandyContext} from './SandyContext';
|
||||
@@ -23,6 +22,7 @@ import {ConsoleLogs} from '../chrome/ConsoleLogs';
|
||||
import {setStaticView} from '../reducers/connections';
|
||||
import {toggleLeftSidebarVisible} from '../reducers/application';
|
||||
import {AppInspect} from './appinspect/AppInspect';
|
||||
import PluginContainer from '../PluginContainer';
|
||||
|
||||
export type ToplevelNavItem = 'appinspect' | 'flipperlogs' | undefined;
|
||||
export type ToplevelProps = {
|
||||
@@ -101,7 +101,7 @@ export function SandyApp({logger}: {logger: Logger}) {
|
||||
logger: logger,
|
||||
})
|
||||
) : (
|
||||
<SandyDesignSystem />
|
||||
<PluginContainer logger={logger} />
|
||||
)}
|
||||
</ContentContainer>
|
||||
<Sidebar
|
||||
|
||||
@@ -7,16 +7,27 @@
|
||||
* @format
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {Alert, Button, Input} from 'antd';
|
||||
import React, {useEffect, useRef, useState} from 'react';
|
||||
import {Alert, Badge, Button, Input, Menu, Tooltip, Typography} from 'antd';
|
||||
import {LeftSidebar, SidebarTitle, InfoIcon} from '../LeftSidebar';
|
||||
import {SettingOutlined, RocketOutlined} from '@ant-design/icons';
|
||||
import {Layout, Link} from '../../ui';
|
||||
import {
|
||||
SettingOutlined,
|
||||
RocketOutlined,
|
||||
MailOutlined,
|
||||
AppstoreOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import {Glyph, Layout, Link, styled} from '../../ui';
|
||||
import {theme} from '../theme';
|
||||
import {useStore as useReduxStore} from 'react-redux';
|
||||
import {showEmulatorLauncher} from './LaunchEmulator';
|
||||
import {AppSelector} from './AppSelector';
|
||||
import {useStore} from '../../utils/useStore';
|
||||
import {useDispatch, useStore} from '../../utils/useStore';
|
||||
import {getPluginTitle, sortPluginsByName} from '../../utils/pluginUtils';
|
||||
import {PluginDefinition} from '../../plugin';
|
||||
import {selectPlugin} from '../../reducers/connections';
|
||||
|
||||
const {SubMenu} = Menu;
|
||||
const {Text} = Typography;
|
||||
|
||||
const appTooltip = (
|
||||
<>
|
||||
@@ -56,7 +67,7 @@ export function AppInspect() {
|
||||
</Layout.Horizontal>
|
||||
</Layout.Vertical>
|
||||
</Layout.Container>
|
||||
<Layout.Container padv={theme.space.small}>
|
||||
<Layout.Container padv={theme.space.large}>
|
||||
{selectedDevice ? (
|
||||
<PluginList />
|
||||
) : (
|
||||
@@ -69,9 +80,214 @@ export function AppInspect() {
|
||||
}
|
||||
|
||||
function PluginList() {
|
||||
// const {selectedApp, selectedDevice} = useStore((state) => state.connections);
|
||||
|
||||
return (
|
||||
<Layout.Container>
|
||||
<SidebarTitle>Plugins</SidebarTitle>
|
||||
<Layout.Container padv={theme.space.small} padh={theme.space.tiny}>
|
||||
<PluginMenu
|
||||
inlineIndent={8}
|
||||
onClick={() => {}}
|
||||
defaultOpenKeys={['device']}
|
||||
mode="inline">
|
||||
<DevicePlugins key="device" />
|
||||
<SubMenu
|
||||
key="sub1"
|
||||
title={
|
||||
<Layout.Right center>
|
||||
<Text strong>Header</Text>
|
||||
<Badge count={8}></Badge>
|
||||
</Layout.Right>
|
||||
}>
|
||||
<Menu.Item key="1" icon={<AppstoreOutlined />}>
|
||||
Option 1
|
||||
</Menu.Item>
|
||||
<Menu.Item key="2" icon={<AppstoreOutlined />}>
|
||||
Option 2
|
||||
</Menu.Item>
|
||||
<Menu.Item key="3">Option 3</Menu.Item>
|
||||
<Menu.Item key="4">Option 4</Menu.Item>
|
||||
</SubMenu>
|
||||
<SubMenu
|
||||
key="sub2"
|
||||
icon={<AppstoreOutlined />}
|
||||
title="Navigation Two">
|
||||
<Menu.Item key="5">Option 5</Menu.Item>
|
||||
<Menu.Item key="6">Option 6</Menu.Item>
|
||||
<Menu.Item key="7">Option 7</Menu.Item>
|
||||
<Menu.Item key="8">Option 8</Menu.Item>
|
||||
</SubMenu>
|
||||
<SubMenu
|
||||
key="sub4"
|
||||
title={
|
||||
<span>
|
||||
<SettingOutlined />
|
||||
<span>Navigation Three</span>
|
||||
</span>
|
||||
}>
|
||||
<Menu.Item key="9">Option 9</Menu.Item>
|
||||
<Menu.Item key="10">Option 10</Menu.Item>
|
||||
<Menu.Item key="11">Option 11</Menu.Item>
|
||||
<Menu.Item key="12">Option 12</Menu.Item>
|
||||
</SubMenu>
|
||||
</PluginMenu>
|
||||
</Layout.Container>
|
||||
</Layout.Container>
|
||||
);
|
||||
}
|
||||
|
||||
function DevicePlugins(props: any) {
|
||||
const dispatch = useDispatch();
|
||||
const {selectedDevice, selectedPlugin} = useStore(
|
||||
(state) => state.connections,
|
||||
);
|
||||
const devicePlugins = useStore((state) => state.plugins.devicePlugins);
|
||||
if (selectedDevice?.devicePlugins.length === 0) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<SubMenu {...props} title={<Text strong>Device</Text>}>
|
||||
{selectedDevice!.devicePlugins
|
||||
.map((pluginName) => devicePlugins.get(pluginName)!)
|
||||
.sort(sortPluginsByName)
|
||||
.map((plugin) => (
|
||||
<Plugin
|
||||
key={plugin.id}
|
||||
isActive={plugin.id === selectedPlugin}
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
selectPlugin({
|
||||
selectedPlugin: plugin.id,
|
||||
selectedApp: null,
|
||||
deepLinkPayload: null,
|
||||
selectedDevice,
|
||||
}),
|
||||
);
|
||||
}}
|
||||
plugin={plugin}
|
||||
/>
|
||||
))}
|
||||
</SubMenu>
|
||||
);
|
||||
}
|
||||
|
||||
const Plugin: React.FC<{
|
||||
onClick: () => void;
|
||||
isActive: boolean;
|
||||
plugin: PluginDefinition;
|
||||
app?: string | null | undefined;
|
||||
helpRef?: any;
|
||||
provided?: any;
|
||||
onFavorite?: () => void;
|
||||
starred?: boolean; // undefined means: not starrable
|
||||
}> = function (props) {
|
||||
const {isActive, plugin, onFavorite, starred, ...rest} = props;
|
||||
const domRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const node = domRef.current;
|
||||
if (isActive && node) {
|
||||
const rect = node.getBoundingClientRect();
|
||||
if (rect.top < 0 || rect.bottom > document.documentElement.clientHeight) {
|
||||
node.scrollIntoView();
|
||||
}
|
||||
}
|
||||
}, [isActive]);
|
||||
|
||||
return (
|
||||
<Menu.Item
|
||||
{...rest}
|
||||
active={isActive}
|
||||
onClick={props.onClick}
|
||||
disabled={starred === false}>
|
||||
<Tooltip
|
||||
placement="right"
|
||||
title={
|
||||
<>
|
||||
{getPluginTitle(plugin)} ({plugin.version})
|
||||
{plugin.details?.description ? (
|
||||
<>
|
||||
<br />
|
||||
<br />
|
||||
{plugin.details?.description}
|
||||
</>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
</>
|
||||
}
|
||||
mouseEnterDelay={1}>
|
||||
<Layout.Horizontal center gap={10} ref={domRef}>
|
||||
<PluginIconWrapper>
|
||||
<Glyph size={16} name={plugin.icon || 'apps'} color="white" />
|
||||
</PluginIconWrapper>
|
||||
{getPluginTitle(plugin)}
|
||||
</Layout.Horizontal>
|
||||
</Tooltip>
|
||||
{/* {starred !== undefined && (!starred || isActive) && (
|
||||
<ToggleButton
|
||||
onClick={onFavorite}
|
||||
toggled={starred}
|
||||
tooltip="Click to enable / disable this plugin"
|
||||
/>
|
||||
)} */}
|
||||
</Menu.Item>
|
||||
);
|
||||
};
|
||||
|
||||
const iconStyle = {
|
||||
color: theme.white,
|
||||
background: theme.primaryColor,
|
||||
borderRadius: theme.borderRadius,
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
|
||||
// TODO: move this largely to themes/base.less to make it the default?
|
||||
// Dimensions are hardcoded as they correlate strongly
|
||||
const PluginMenu = styled(Menu)({
|
||||
border: 'none',
|
||||
'.ant-menu-inline .ant-menu-item, .ant-menu-inline .ant-menu-submenu-title ': {
|
||||
width: '100%', // reset to remove weird bonus pixel from ANT
|
||||
},
|
||||
'.ant-menu-submenu > .ant-menu-submenu-title, .ant-menu-sub.ant-menu-inline > .ant-menu-item': {
|
||||
borderRadius: theme.borderRadius,
|
||||
height: '32px',
|
||||
lineHeight: '24px',
|
||||
padding: `4px 32px 4px 8px !important`,
|
||||
'&:hover': {
|
||||
color: theme.textColorPrimary,
|
||||
background: theme.backgroundTransparentHover,
|
||||
},
|
||||
'&.ant-menu-item-selected::after': {
|
||||
border: 'none',
|
||||
},
|
||||
'&.ant-menu-item-selected': {
|
||||
color: theme.white,
|
||||
background: theme.primaryColor,
|
||||
border: 'none',
|
||||
},
|
||||
},
|
||||
'.ant-menu-submenu-inline > .ant-menu-submenu-title .ant-menu-submenu-arrow': {
|
||||
right: 8,
|
||||
},
|
||||
'.ant-badge-count': {
|
||||
color: theme.textColorPrimary,
|
||||
background: theme.backgroundTransparentHover,
|
||||
fontWeight: 'bold',
|
||||
padding: `0 10px`,
|
||||
boxShadow: 'none',
|
||||
},
|
||||
'.ant-menu-item .anticon': {
|
||||
...iconStyle,
|
||||
lineHeight: '28px', // WUT?
|
||||
},
|
||||
});
|
||||
|
||||
const PluginIconWrapper = styled.div({
|
||||
...iconStyle,
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
});
|
||||
|
||||
@@ -107,6 +107,7 @@ const AppInspectButton = styled(Button)({
|
||||
});
|
||||
|
||||
const AppIcon = styled.div<{appname?: string}>(({appname}) => ({
|
||||
borderRadius: 4,
|
||||
width: 36,
|
||||
height: 36,
|
||||
background: appname
|
||||
|
||||
@@ -69,7 +69,7 @@ export function LaunchEmulatorDialog({
|
||||
launchEmulator(name)
|
||||
.catch((e) => {
|
||||
console.error(e);
|
||||
message.error('Failed to start emulator:' + e);
|
||||
message.error('Failed to start emulator: ' + e);
|
||||
})
|
||||
.finally(onClose);
|
||||
}}>
|
||||
@@ -84,7 +84,7 @@ export function LaunchEmulatorDialog({
|
||||
launchSimulator(device.udid)
|
||||
.catch((e) => {
|
||||
console.error(e);
|
||||
message.error('Failed to start simulator:' + e);
|
||||
message.error('Failed to start simulator: ' + e);
|
||||
})
|
||||
.finally(onClose);
|
||||
}}>
|
||||
|
||||
@@ -12,6 +12,7 @@ import {useStore} from '../utils/useStore';
|
||||
// Exposes all the variables defined in themes/base.less:
|
||||
|
||||
export const theme = {
|
||||
white: 'white', // use as counter color for primary
|
||||
primaryColor: 'var(--flipper-primary-color)',
|
||||
successColor: 'var(--flipper-success-color)',
|
||||
errorColor: 'var(--flipper-error-color)',
|
||||
|
||||
@@ -204,12 +204,13 @@ Object.keys(Layout).forEach((key) => {
|
||||
const SandySplitContainer = styled.div<{
|
||||
flex1: number;
|
||||
flex2: number;
|
||||
center?: boolean;
|
||||
flexDirection: CSSProperties['flexDirection'];
|
||||
}>((props) => ({
|
||||
display: 'flex',
|
||||
flex: 1,
|
||||
flexDirection: props.flexDirection,
|
||||
alignItems: 'stretch',
|
||||
alignItems: props.center ? 'center' : 'stretch',
|
||||
'> :first-child': {
|
||||
flexGrow: props.flex1,
|
||||
flexShrink: props.flex1,
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
* @format
|
||||
*/
|
||||
|
||||
import {theme} from '../../sandy-chrome/theme';
|
||||
|
||||
// Last updated: Jan 30 2016
|
||||
|
||||
export const colors = {
|
||||
@@ -278,5 +280,5 @@ export const brandColors = {
|
||||
Facebook: '#0D7BED',
|
||||
Messenger: '#0088FA',
|
||||
Instagram: '#E61E68',
|
||||
Flipper: '#8155cb',
|
||||
Flipper: theme.primaryColor,
|
||||
};
|
||||
|
||||
@@ -7,13 +7,16 @@
|
||||
12
|
||||
],
|
||||
"app-react": [
|
||||
12
|
||||
12,
|
||||
16
|
||||
],
|
||||
"apps": [
|
||||
12
|
||||
12,
|
||||
16
|
||||
],
|
||||
"arrow-right": [
|
||||
12
|
||||
12,
|
||||
16
|
||||
],
|
||||
"bell-null-outline": [
|
||||
24
|
||||
@@ -336,7 +339,8 @@
|
||||
16
|
||||
],
|
||||
"code": [
|
||||
12
|
||||
12,
|
||||
16
|
||||
],
|
||||
"undo-outline": [
|
||||
16
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
// Based on: https://www.figma.com/file/4e6BMdm2SuZ1L7FSuOPQVC/Flipper?node-id=620%3A84614
|
||||
|
||||
// Link Text & Icon
|
||||
@primary-color: @purple-7;
|
||||
@primary-color: #722ED1;
|
||||
// Success
|
||||
@success-color: @green-7;
|
||||
// Negative
|
||||
|
||||
Reference in New Issue
Block a user