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:
committed by
Facebook GitHub Bot
parent
9deed974be
commit
3484f321af
@@ -19,6 +19,7 @@ import {
|
|||||||
SettingOutlined,
|
SettingOutlined,
|
||||||
QuestionCircleOutlined,
|
QuestionCircleOutlined,
|
||||||
MedicineBoxOutlined,
|
MedicineBoxOutlined,
|
||||||
|
RocketOutlined,
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import {SidebarLeft, SidebarRight} from './SandyIcons';
|
import {SidebarLeft, SidebarRight} from './SandyIcons';
|
||||||
import {useDispatch, useStore} from '../utils/useStore';
|
import {useDispatch, useStore} from '../utils/useStore';
|
||||||
@@ -37,6 +38,8 @@ import {useValue} from 'flipper-plugin';
|
|||||||
import {logout} from '../reducers/user';
|
import {logout} from '../reducers/user';
|
||||||
import config from '../fb-stubs/config';
|
import config from '../fb-stubs/config';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
import {showEmulatorLauncher} from './appinspect/LaunchEmulator';
|
||||||
|
import {useStore as useReduxStore} from 'react-redux';
|
||||||
|
|
||||||
const LeftRailButtonElem = styled(Button)<{kind?: 'small'}>(({kind}) => ({
|
const LeftRailButtonElem = styled(Button)<{kind?: 'small'}>(({kind}) => ({
|
||||||
width: kind === 'small' ? 32 : 36,
|
width: kind === 'small' ? 32 : 36,
|
||||||
@@ -128,6 +131,7 @@ export function LeftRail({
|
|||||||
/>
|
/>
|
||||||
</Layout.Container>
|
</Layout.Container>
|
||||||
<Layout.Container center gap={10} padh={6}>
|
<Layout.Container center gap={10} padh={6}>
|
||||||
|
<LaunchEmulatorButton />
|
||||||
<SetupDoctorButton />
|
<SetupDoctorButton />
|
||||||
<WelcomeScreenButton />
|
<WelcomeScreenButton />
|
||||||
<ShowSettingsButton />
|
<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() {
|
function SetupDoctorButton() {
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
const result = useStore(
|
const result = useStore(
|
||||||
|
|||||||
@@ -8,13 +8,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {Alert, Button, Input} from 'antd';
|
import {Alert, Input} from 'antd';
|
||||||
import {LeftSidebar, SidebarTitle, InfoIcon} from '../LeftSidebar';
|
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 {Layout, Link, styled} from '../../ui';
|
||||||
import {theme} from 'flipper-plugin';
|
import {theme} from 'flipper-plugin';
|
||||||
import {useStore as useReduxStore} from 'react-redux';
|
|
||||||
import {showEmulatorLauncher} from './LaunchEmulator';
|
|
||||||
import {AppSelector} from './AppSelector';
|
import {AppSelector} from './AppSelector';
|
||||||
import {useStore} from '../../utils/useStore';
|
import {useStore} from '../../utils/useStore';
|
||||||
import {PluginList} from './PluginList';
|
import {PluginList} from './PluginList';
|
||||||
@@ -33,8 +31,8 @@ const appTooltip = (
|
|||||||
);
|
);
|
||||||
|
|
||||||
export function AppInspect() {
|
export function AppInspect() {
|
||||||
const store = useReduxStore();
|
|
||||||
const selectedDevice = useStore((state) => state.connections.selectedDevice);
|
const selectedDevice = useStore((state) => state.connections.selectedDevice);
|
||||||
|
const isArchived = !!selectedDevice?.isArchived;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LeftSidebar>
|
<LeftSidebar>
|
||||||
@@ -45,26 +43,27 @@ export function AppInspect() {
|
|||||||
</SidebarTitle>
|
</SidebarTitle>
|
||||||
<Layout.Container padv="small" padh="medium" gap={theme.space.large}>
|
<Layout.Container padv="small" padh="medium" gap={theme.space.large}>
|
||||||
<AppSelector />
|
<AppSelector />
|
||||||
<Input addonAfter={<SettingOutlined />} defaultValue="mysite" />
|
{isArchived ? (
|
||||||
<Toolbar gap>
|
<Alert
|
||||||
<Button
|
message="This device is a snapshot and cannot be interacted with."
|
||||||
icon={<RocketOutlined />}
|
type="info"
|
||||||
type="ghost"
|
|
||||||
title="Start Emulator / Simulator..."
|
|
||||||
onClick={() => {
|
|
||||||
showEmulatorLauncher(store);
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
<MetroButton useSandy />
|
) : (
|
||||||
<ScreenCaptureButtons useSandy />
|
<Input addonAfter={<SettingOutlined />} defaultValue="mysite" />
|
||||||
</Toolbar>
|
)}
|
||||||
|
{!isArchived && (
|
||||||
|
<Toolbar gap>
|
||||||
|
<MetroButton useSandy />
|
||||||
|
<ScreenCaptureButtons useSandy />
|
||||||
|
</Toolbar>
|
||||||
|
)}
|
||||||
</Layout.Container>
|
</Layout.Container>
|
||||||
</Layout.Container>
|
</Layout.Container>
|
||||||
<Layout.ScrollContainer vertical padv={theme.space.large}>
|
<Layout.ScrollContainer vertical padv={theme.space.large}>
|
||||||
{selectedDevice ? (
|
{selectedDevice ? (
|
||||||
<PluginList />
|
<PluginList />
|
||||||
) : (
|
) : (
|
||||||
<Alert message="No device or app selected" type="info" />
|
<Alert message="No device or app selected." type="info" />
|
||||||
)}
|
)}
|
||||||
</Layout.ScrollContainer>
|
</Layout.ScrollContainer>
|
||||||
</Layout.Top>
|
</Layout.Top>
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ export const PluginList = memo(function PluginList() {
|
|||||||
plugins,
|
plugins,
|
||||||
connections.userStarredPlugins,
|
connections.userStarredPlugins,
|
||||||
]);
|
]);
|
||||||
|
const isArchived = !!activeDevice?.isArchived;
|
||||||
|
|
||||||
const handleAppPluginClick = useCallback(
|
const handleAppPluginClick = useCallback(
|
||||||
(pluginId) => {
|
(pluginId) => {
|
||||||
@@ -122,20 +123,22 @@ export const PluginList = memo(function PluginList() {
|
|||||||
))}
|
))}
|
||||||
</PluginGroup>
|
</PluginGroup>
|
||||||
|
|
||||||
<PluginGroup key="metro" title="React Native">
|
{!isArchived && (
|
||||||
{metroPlugins.map((plugin) => (
|
<PluginGroup key="metro" title="React Native">
|
||||||
<PluginEntry
|
{metroPlugins.map((plugin) => (
|
||||||
key={'metro' + plugin.id}
|
<PluginEntry
|
||||||
plugin={plugin.details}
|
key={'metro' + plugin.id}
|
||||||
active={
|
plugin={plugin.details}
|
||||||
plugin.id === connections.selectedPlugin &&
|
active={
|
||||||
connections.selectedDevice === metroDevice
|
plugin.id === connections.selectedPlugin &&
|
||||||
}
|
connections.selectedDevice === metroDevice
|
||||||
onClick={handleMetroPluginClick}
|
}
|
||||||
tooltip={getPluginTooltip(plugin.details)}
|
onClick={handleMetroPluginClick}
|
||||||
/>
|
tooltip={getPluginTooltip(plugin.details)}
|
||||||
))}
|
/>
|
||||||
</PluginGroup>
|
))}
|
||||||
|
</PluginGroup>
|
||||||
|
)}
|
||||||
<PluginGroup key="enabled" title="Enabled">
|
<PluginGroup key="enabled" title="Enabled">
|
||||||
{enabledPlugins.map((plugin) => (
|
{enabledPlugins.map((plugin) => (
|
||||||
<PluginEntry
|
<PluginEntry
|
||||||
@@ -145,48 +148,56 @@ export const PluginList = memo(function PluginList() {
|
|||||||
onClick={handleAppPluginClick}
|
onClick={handleAppPluginClick}
|
||||||
tooltip={getPluginTooltip(plugin.details)}
|
tooltip={getPluginTooltip(plugin.details)}
|
||||||
actions={
|
actions={
|
||||||
<ActionButton
|
isArchived ? null : (
|
||||||
id={plugin.id}
|
<ActionButton
|
||||||
onClick={handleStarPlugin}
|
id={plugin.id}
|
||||||
title="Disable plugin"
|
onClick={handleStarPlugin}
|
||||||
icon={<MinusOutlined size={16} style={{marginRight: 0}} />}
|
title="Disable plugin"
|
||||||
/>
|
icon={
|
||||||
|
<MinusOutlined size={16} style={{marginRight: 0}} />
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</PluginGroup>
|
</PluginGroup>
|
||||||
<PluginGroup key="disabled" title="Disabled">
|
{!isArchived && (
|
||||||
{disabledPlugins.map((plugin) => (
|
<PluginGroup key="disabled" title="Disabled">
|
||||||
<PluginEntry
|
{disabledPlugins.map((plugin) => (
|
||||||
key={plugin.id}
|
<PluginEntry
|
||||||
plugin={plugin.details}
|
key={plugin.id}
|
||||||
active={plugin.id === connections.selectedPlugin}
|
plugin={plugin.details}
|
||||||
tooltip={getPluginTooltip(plugin.details)}
|
active={plugin.id === connections.selectedPlugin}
|
||||||
actions={
|
tooltip={getPluginTooltip(plugin.details)}
|
||||||
<ActionButton
|
actions={
|
||||||
id={plugin.id}
|
<ActionButton
|
||||||
title="Enable plugin"
|
id={plugin.id}
|
||||||
onClick={handleStarPlugin}
|
title="Enable plugin"
|
||||||
icon={<PlusOutlined size={16} style={{marginRight: 0}} />}
|
onClick={handleStarPlugin}
|
||||||
/>
|
icon={<PlusOutlined size={16} style={{marginRight: 0}} />}
|
||||||
}
|
/>
|
||||||
disabled
|
}
|
||||||
/>
|
disabled
|
||||||
))}
|
/>
|
||||||
</PluginGroup>
|
))}
|
||||||
<PluginGroup key="unavailable" title="Unavailable plugins">
|
</PluginGroup>
|
||||||
{unavailablePlugins.map(([plugin, reason]) => (
|
)}
|
||||||
<PluginEntry
|
{!isArchived && (
|
||||||
key={plugin.id}
|
<PluginGroup key="unavailable" title="Unavailable plugins">
|
||||||
plugin={plugin}
|
{unavailablePlugins.map(([plugin, reason]) => (
|
||||||
tooltip={`${getPluginTitle(plugin)} (${plugin.id}@${
|
<PluginEntry
|
||||||
plugin.version
|
key={plugin.id}
|
||||||
}): ${reason}`}
|
plugin={plugin}
|
||||||
disabled
|
tooltip={`${getPluginTitle(plugin)} (${plugin.id}@${
|
||||||
actions={<InfoIcon>{reason}</InfoIcon>}
|
plugin.version
|
||||||
/>
|
}): ${reason}`}
|
||||||
))}
|
disabled
|
||||||
</PluginGroup>
|
actions={<InfoIcon>{reason}</InfoIcon>}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</PluginGroup>
|
||||||
|
)}
|
||||||
</PluginMenu>
|
</PluginMenu>
|
||||||
</Layout.Container>
|
</Layout.Container>
|
||||||
</Layout.Container>
|
</Layout.Container>
|
||||||
@@ -231,7 +242,7 @@ const PluginEntry = memo(function PluginEntry({
|
|||||||
active?: boolean;
|
active?: boolean;
|
||||||
tooltip: string;
|
tooltip: string;
|
||||||
onClick?: (id: string) => void;
|
onClick?: (id: string) => void;
|
||||||
actions?: React.ReactElement;
|
actions?: React.ReactElement | null;
|
||||||
}) {
|
}) {
|
||||||
const [hovering, setHovering] = useState(false);
|
const [hovering, setHovering] = useState(false);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user