Support archived devices

Summary:
Make sure archived are displayed as such in the UI, and normal device functions aren't available:

* taking screenshots
* bookmarks
* metro device plugins
* disabling plugins
* disabled and unavailable plugins
* mobile builds

Also moved starting an emulator to the left rail, since it isn't a function related to the current selected thing

Reviewed By: cekkaewnumchai

Differential Revision: D24620247

fbshipit-source-id: f1f469e2fc5167fd90ccb35d583988873a9bc787
This commit is contained in:
Michel Weststrate
2020-10-30 04:20:00 -07:00
committed by Facebook GitHub Bot
parent 9deed974be
commit 3484f321af
3 changed files with 100 additions and 71 deletions

View File

@@ -19,6 +19,7 @@ import {
SettingOutlined,
QuestionCircleOutlined,
MedicineBoxOutlined,
RocketOutlined,
} from '@ant-design/icons';
import {SidebarLeft, SidebarRight} from './SandyIcons';
import {useDispatch, useStore} from '../utils/useStore';
@@ -37,6 +38,8 @@ import {useValue} from 'flipper-plugin';
import {logout} from '../reducers/user';
import config from '../fb-stubs/config';
import styled from '@emotion/styled';
import {showEmulatorLauncher} from './appinspect/LaunchEmulator';
import {useStore as useReduxStore} from 'react-redux';
const LeftRailButtonElem = styled(Button)<{kind?: 'small'}>(({kind}) => ({
width: kind === 'small' ? 32 : 36,
@@ -128,6 +131,7 @@ export function LeftRail({
/>
</Layout.Container>
<Layout.Container center gap={10} padh={6}>
<LaunchEmulatorButton />
<SetupDoctorButton />
<WelcomeScreenButton />
<ShowSettingsButton />
@@ -223,6 +227,21 @@ function DebugLogsButton({
);
}
function LaunchEmulatorButton() {
const store = useReduxStore();
return (
<LeftRailButton
icon={<RocketOutlined />}
title="Start Emulator / Simulator"
onClick={() => {
showEmulatorLauncher(store);
}}
small
/>
);
}
function SetupDoctorButton() {
const [visible, setVisible] = useState(false);
const result = useStore(

View File

@@ -8,13 +8,11 @@
*/
import React from 'react';
import {Alert, Button, Input} from 'antd';
import {Alert, Input} from 'antd';
import {LeftSidebar, SidebarTitle, InfoIcon} from '../LeftSidebar';
import {SettingOutlined, RocketOutlined} from '@ant-design/icons';
import {SettingOutlined} from '@ant-design/icons';
import {Layout, Link, styled} from '../../ui';
import {theme} from 'flipper-plugin';
import {useStore as useReduxStore} from 'react-redux';
import {showEmulatorLauncher} from './LaunchEmulator';
import {AppSelector} from './AppSelector';
import {useStore} from '../../utils/useStore';
import {PluginList} from './PluginList';
@@ -33,8 +31,8 @@ const appTooltip = (
);
export function AppInspect() {
const store = useReduxStore();
const selectedDevice = useStore((state) => state.connections.selectedDevice);
const isArchived = !!selectedDevice?.isArchived;
return (
<LeftSidebar>
@@ -45,26 +43,27 @@ export function AppInspect() {
</SidebarTitle>
<Layout.Container padv="small" padh="medium" gap={theme.space.large}>
<AppSelector />
<Input addonAfter={<SettingOutlined />} defaultValue="mysite" />
<Toolbar gap>
<Button
icon={<RocketOutlined />}
type="ghost"
title="Start Emulator / Simulator..."
onClick={() => {
showEmulatorLauncher(store);
}}
{isArchived ? (
<Alert
message="This device is a snapshot and cannot be interacted with."
type="info"
/>
<MetroButton useSandy />
<ScreenCaptureButtons useSandy />
</Toolbar>
) : (
<Input addonAfter={<SettingOutlined />} defaultValue="mysite" />
)}
{!isArchived && (
<Toolbar gap>
<MetroButton useSandy />
<ScreenCaptureButtons useSandy />
</Toolbar>
)}
</Layout.Container>
</Layout.Container>
<Layout.ScrollContainer vertical padv={theme.space.large}>
{selectedDevice ? (
<PluginList />
) : (
<Alert message="No device or app selected" type="info" />
<Alert message="No device or app selected." type="info" />
)}
</Layout.ScrollContainer>
</Layout.Top>

View File

@@ -59,6 +59,7 @@ export const PluginList = memo(function PluginList() {
plugins,
connections.userStarredPlugins,
]);
const isArchived = !!activeDevice?.isArchived;
const handleAppPluginClick = useCallback(
(pluginId) => {
@@ -122,20 +123,22 @@ export const PluginList = memo(function PluginList() {
))}
</PluginGroup>
<PluginGroup key="metro" title="React Native">
{metroPlugins.map((plugin) => (
<PluginEntry
key={'metro' + plugin.id}
plugin={plugin.details}
active={
plugin.id === connections.selectedPlugin &&
connections.selectedDevice === metroDevice
}
onClick={handleMetroPluginClick}
tooltip={getPluginTooltip(plugin.details)}
/>
))}
</PluginGroup>
{!isArchived && (
<PluginGroup key="metro" title="React Native">
{metroPlugins.map((plugin) => (
<PluginEntry
key={'metro' + plugin.id}
plugin={plugin.details}
active={
plugin.id === connections.selectedPlugin &&
connections.selectedDevice === metroDevice
}
onClick={handleMetroPluginClick}
tooltip={getPluginTooltip(plugin.details)}
/>
))}
</PluginGroup>
)}
<PluginGroup key="enabled" title="Enabled">
{enabledPlugins.map((plugin) => (
<PluginEntry
@@ -145,48 +148,56 @@ export const PluginList = memo(function PluginList() {
onClick={handleAppPluginClick}
tooltip={getPluginTooltip(plugin.details)}
actions={
<ActionButton
id={plugin.id}
onClick={handleStarPlugin}
title="Disable plugin"
icon={<MinusOutlined size={16} style={{marginRight: 0}} />}
/>
isArchived ? null : (
<ActionButton
id={plugin.id}
onClick={handleStarPlugin}
title="Disable plugin"
icon={
<MinusOutlined size={16} style={{marginRight: 0}} />
}
/>
)
}
/>
))}
</PluginGroup>
<PluginGroup key="disabled" title="Disabled">
{disabledPlugins.map((plugin) => (
<PluginEntry
key={plugin.id}
plugin={plugin.details}
active={plugin.id === connections.selectedPlugin}
tooltip={getPluginTooltip(plugin.details)}
actions={
<ActionButton
id={plugin.id}
title="Enable plugin"
onClick={handleStarPlugin}
icon={<PlusOutlined size={16} style={{marginRight: 0}} />}
/>
}
disabled
/>
))}
</PluginGroup>
<PluginGroup key="unavailable" title="Unavailable plugins">
{unavailablePlugins.map(([plugin, reason]) => (
<PluginEntry
key={plugin.id}
plugin={plugin}
tooltip={`${getPluginTitle(plugin)} (${plugin.id}@${
plugin.version
}): ${reason}`}
disabled
actions={<InfoIcon>{reason}</InfoIcon>}
/>
))}
</PluginGroup>
{!isArchived && (
<PluginGroup key="disabled" title="Disabled">
{disabledPlugins.map((plugin) => (
<PluginEntry
key={plugin.id}
plugin={plugin.details}
active={plugin.id === connections.selectedPlugin}
tooltip={getPluginTooltip(plugin.details)}
actions={
<ActionButton
id={plugin.id}
title="Enable plugin"
onClick={handleStarPlugin}
icon={<PlusOutlined size={16} style={{marginRight: 0}} />}
/>
}
disabled
/>
))}
</PluginGroup>
)}
{!isArchived && (
<PluginGroup key="unavailable" title="Unavailable plugins">
{unavailablePlugins.map(([plugin, reason]) => (
<PluginEntry
key={plugin.id}
plugin={plugin}
tooltip={`${getPluginTitle(plugin)} (${plugin.id}@${
plugin.version
}): ${reason}`}
disabled
actions={<InfoIcon>{reason}</InfoIcon>}
/>
))}
</PluginGroup>
)}
</PluginMenu>
</Layout.Container>
</Layout.Container>
@@ -231,7 +242,7 @@ const PluginEntry = memo(function PluginEntry({
active?: boolean;
tooltip: string;
onClick?: (id: string) => void;
actions?: React.ReactElement;
actions?: React.ReactElement | null;
}) {
const [hovering, setHovering] = useState(false);