no client/device

Summary:
Plugin debugger is now supporting 3 different scenarios:
- no devices connected
- device connected, but no app for the selected device is connected
- apps are connected

Added button to the sidebar to open plugin debugger.

Reviewed By: passy

Differential Revision: D13608749

fbshipit-source-id: d5ba04882590dace78e4ef0b17799d5a394dc3c4
This commit is contained in:
Daniel Büchele
2019-01-09 10:02:55 -08:00
committed by Facebook Github Bot
parent 36b109ecc6
commit 422ab99d29
2 changed files with 198 additions and 104 deletions

View File

@@ -21,6 +21,7 @@ import {
Text, Text,
Glyph, Glyph,
styled, styled,
FlexColumn,
GK, GK,
FlipperPlugin, FlipperPlugin,
FlipperDevicePlugin, FlipperDevicePlugin,
@@ -29,6 +30,7 @@ import {
import React from 'react'; import React from 'react';
import NotificationsHub from '../NotificationsHub.js'; import NotificationsHub from '../NotificationsHub.js';
import {selectPlugin} from '../reducers/connections.js'; import {selectPlugin} from '../reducers/connections.js';
import {setActiveSheet} from '../reducers/application.js';
import {connect} from 'react-redux'; import {connect} from 'react-redux';
const ListItem = styled('div')(({active}) => ({ const ListItem = styled('div')(({active}) => ({
@@ -97,6 +99,20 @@ const PluginName = styled(Text)(props => ({
}, },
})); }));
const Plugins = styled(FlexColumn)({
flexGrow: 1,
});
const PluginDebugger = styled(FlexBox)(props => ({
color: colors.blackAlpha50,
borderTop: `1px solid ${colors.blackAlpha10}`,
alignItems: 'center',
padding: 10,
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis',
}));
function PluginIcon({ function PluginIcon({
isActive, isActive,
backgroundColor, backgroundColor,
@@ -188,6 +204,7 @@ type MainSidebarProps = {|
numNotifications: number, numNotifications: number,
devicePlugins: Map<string, Class<FlipperDevicePlugin<>>>, devicePlugins: Map<string, Class<FlipperDevicePlugin<>>>,
clientPlugins: Map<string, Class<FlipperPlugin<>>>, clientPlugins: Map<string, Class<FlipperPlugin<>>>,
setActiveSheet: (activeSheet: ?string) => any,
|}; |};
class MainSidebar extends PureComponent<MainSidebarProps> { class MainSidebar extends PureComponent<MainSidebarProps> {
@@ -216,98 +233,111 @@ class MainSidebar extends PureComponent<MainSidebarProps> {
backgroundColor={ backgroundColor={
process.platform === 'darwin' && windowIsFocused ? 'transparent' : '' process.platform === 'darwin' && windowIsFocused ? 'transparent' : ''
}> }>
{!GK.get('flipper_disable_notifications') && ( <Plugins>
<ListItem {!GK.get('flipper_disable_notifications') && (
active={selectedPlugin === 'notifications'} <ListItem
onClick={() => active={selectedPlugin === 'notifications'}
selectPlugin({ onClick={() =>
selectedPlugin: 'notifications', selectPlugin({
selectedApp: null, selectedPlugin: 'notifications',
deepLinkPayload: null, selectedApp: null,
}) deepLinkPayload: null,
}> })
<PluginIcon }>
color={colors.light50} <PluginIcon
name={ color={colors.light50}
numNotifications > 0 name={
? NotificationsHub.icon || 'bell' numNotifications > 0
: 'bell-null' ? NotificationsHub.icon || 'bell'
} : 'bell-null'
isActive={selectedPlugin === NotificationsHub.id}
/>
<PluginName
count={numNotifications}
isActive={selectedPlugin === NotificationsHub.id}>
{NotificationsHub.title}
</PluginName>
</ListItem>
)}
{selectedDevice && (
<SidebarHeader>{selectedDevice.title}</SidebarHeader>
)}
{selectedDevice &&
Array.from(this.props.devicePlugins.values())
.filter(plugin => plugin.supportsDevice(selectedDevice))
.map((plugin: Class<FlipperDevicePlugin<>>) => (
<PluginSidebarListItem
key={plugin.id}
isActive={plugin.id === selectedPlugin}
onClick={() =>
selectPlugin({
selectedPlugin: plugin.id,
selectedApp: null,
deepLinkPayload: null,
})
} }
plugin={plugin} isActive={selectedPlugin === NotificationsHub.id}
/> />
<PluginName
count={numNotifications}
isActive={selectedPlugin === NotificationsHub.id}>
{NotificationsHub.title}
</PluginName>
</ListItem>
)}
{selectedDevice && (
<SidebarHeader>{selectedDevice.title}</SidebarHeader>
)}
{selectedDevice &&
Array.from(this.props.devicePlugins.values())
.filter(plugin => plugin.supportsDevice(selectedDevice))
.map((plugin: Class<FlipperDevicePlugin<>>) => (
<PluginSidebarListItem
key={plugin.id}
isActive={plugin.id === selectedPlugin}
onClick={() =>
selectPlugin({
selectedPlugin: plugin.id,
selectedApp: null,
deepLinkPayload: null,
})
}
plugin={plugin}
/>
))}
{clients
.filter(
(client: Client) =>
(selectedDevice &&
client.query.device_id === selectedDevice.serial) ||
// Old android sdk versions don't know their device_id
// Display their plugins under all selected devices until they die out
client.query.device_id === 'unknown',
)
.map((client: Client) => (
<React.Fragment key={client.id}>
<SidebarHeader>{client.query.app}</SidebarHeader>
{Array.from(this.props.clientPlugins.values())
.filter(
(p: Class<FlipperPlugin<>>) =>
client.plugins.indexOf(p.id) > -1,
)
.map((plugin: Class<FlipperPlugin<>>) => (
<PluginSidebarListItem
key={plugin.id}
isActive={
plugin.id === selectedPlugin &&
selectedApp === client.id
}
onClick={() =>
selectPlugin({
selectedPlugin: plugin.id,
selectedApp: client.id,
deepLinkPayload: null,
})
}
plugin={plugin}
app={client.query.app}
/>
))}
</React.Fragment>
))} ))}
{clients {uninitializedClients.map(entry => (
.filter( <React.Fragment key={JSON.stringify(entry.client)}>
(client: Client) => <SidebarHeader>{entry.client.appName}</SidebarHeader>
(selectedDevice && {entry.errorMessage ? (
client.query.device_id === selectedDevice.serial) || <ErrorIndicator name={'mobile-cross'} size={16} />
// Old android sdk versions don't know their device_id ) : (
// Display their plugins under all selected devices until they die out <Spinner size={16} />
client.query.device_id === 'unknown', )}
)
.map((client: Client) => (
<React.Fragment key={client.id}>
<SidebarHeader>{client.query.app}</SidebarHeader>
{Array.from(this.props.clientPlugins.values())
.filter(
(p: Class<FlipperPlugin<>>) =>
client.plugins.indexOf(p.id) > -1,
)
.map((plugin: Class<FlipperPlugin<>>) => (
<PluginSidebarListItem
key={plugin.id}
isActive={
plugin.id === selectedPlugin && selectedApp === client.id
}
onClick={() =>
selectPlugin({
selectedPlugin: plugin.id,
selectedApp: client.id,
deepLinkPayload: null,
})
}
plugin={plugin}
app={client.query.app}
/>
))}
</React.Fragment> </React.Fragment>
))} ))}
{uninitializedClients.map(entry => ( </Plugins>
<React.Fragment key={JSON.stringify(entry.client)}> <PluginDebugger
<SidebarHeader>{entry.client.appName}</SidebarHeader> onClick={() => this.props.setActiveSheet('PLUGIN_DEBUGGER')}>
{entry.errorMessage ? ( <Glyph
<ErrorIndicator name={'mobile-cross'} size={16} /> name="question-circle"
) : ( size={16}
<Spinner size={16} /> variant="outline"
)} color={colors.blackAlpha30}
</React.Fragment> />
))} &nbsp;Plugin not showing?
</PluginDebugger>
</Sidebar> </Sidebar>
); );
} }
@@ -347,5 +377,6 @@ export default connect(
}), }),
{ {
selectPlugin, selectPlugin,
setActiveSheet,
}, },
)(MainSidebar); )(MainSidebar);

View File

@@ -9,9 +9,17 @@ import type {FlipperDevicePlugin, FlipperPlugin} from '../plugin';
import type {PluginDefinition} from '../dispatcher/plugins'; import type {PluginDefinition} from '../dispatcher/plugins';
import type Client from '../Client'; import type Client from '../Client';
import {Component} from 'react'; import {Component, Fragment} from 'react';
import {connect} from 'react-redux'; import {connect} from 'react-redux';
import {FlexColumn, Button, Text, ManagedTable, styled, colors} from 'flipper'; import {
FlexColumn,
Button,
Text,
ManagedTable,
styled,
colors,
Link,
} from 'flipper';
import {remote} from 'electron'; import {remote} from 'electron';
const Container = styled(FlexColumn)({ const Container = styled(FlexColumn)({
@@ -20,7 +28,8 @@ const Container = styled(FlexColumn)({
}); });
const InfoText = styled(Text)({ const InfoText = styled(Text)({
lineHeight: '140%', lineHeight: '130%',
marginBottom: 8,
}); });
const Title = styled('div')({ const Title = styled('div')({
@@ -67,6 +76,7 @@ type Props = {|
disabledPlugins: Array<PluginDefinition>, disabledPlugins: Array<PluginDefinition>,
failedPlugins: Array<[PluginDefinition, string]>, failedPlugins: Array<[PluginDefinition, string]>,
clients: Array<Client>, clients: Array<Client>,
selectedDevice: ?string,
onHide: () => mixed, onHide: () => mixed,
|}; |};
@@ -217,22 +227,74 @@ class PluginDebugger extends Component<Props> {
} }
render() { render() {
let content = null;
if (!this.props.selectedDevice) {
content = (
<InfoText>
We can't find any device connected to your computer. Is an
emulator/simulator currently running on your system, or is there a
development device connected via USB? There are some devices/emulators
known to have problems connecting to Flipper. Check out the{' '}
<Link href="https://fbflipper.com/docs/troubleshooting.html#known-incompatibilities">
known incompatibilities
</Link>.
</InfoText>
);
} else if (
!this.props.clients.some(
(client: Client) =>
client.query.device_id === this.props.selectedDevice,
)
) {
// no clients for selected device
content = (
<Fragment>
<InfoText>
While Flipper was able to connect to your device, it wasn't able to
connect to the app you are running on your device. For this reason,
app-specific plugins will not show up.
</InfoText>
{this.props.clients.length > 0 && (
// we have clients, but not for this device
<InfoText>
Make sure you selected the correct device from the dropdown button
in the upper left corner. Only plugins for the selected device are
shown in the sidebar.
</InfoText>
)}
<InfoText>
To debug why Flipper couldn't establish a connection to the app,
check out our documentation about{' '}
<Link href="https://fbflipper.com/docs/troubleshooting.html#connection-issues">
connection issues
</Link>.
</InfoText>
</Fragment>
);
} else {
content = (
<Fragment>
<InfoText>
The table lists all plugins known to Flipper. Some of them might be
blocked by GKs, others may not show up, because none of the
connected apps is supporting it.
</InfoText>
<TableContainer>
<ManagedTable
columns={COLUMNS}
rows={this.getRows()}
highlightableRows={false}
columnSizes={COLUMNS_SIZES}
/>
</TableContainer>
</Fragment>
);
}
return ( return (
<Container> <Container>
<Title>Plugin Status</Title> <Title>Plugin Status</Title>
<InfoText> {content}
The table lists all plugins known to Flipper. Some of them might be
blocked by GKs, others may not show up, because none of the connected
apps is supporting it.
</InfoText>
<TableContainer>
<ManagedTable
columns={COLUMNS}
rows={this.getRows()}
highlightableRows={false}
columnSizes={COLUMNS_SIZES}
/>
</TableContainer>
<Row> <Row>
<Button compact padded onClick={this.props.onHide}> <Button compact padded onClick={this.props.onHide}>
Close Close
@@ -253,7 +315,7 @@ export default connect(
disabledPlugins, disabledPlugins,
failedPlugins, failedPlugins,
}, },
connections: {selectedPlugin, clients}, connections: {selectedPlugin, clients, selectedDevice},
}) => ({ }) => ({
devicePlugins: Array.from(devicePlugins.values()), devicePlugins: Array.from(devicePlugins.values()),
clientPlugins: Array.from(clientPlugins.values()), clientPlugins: Array.from(clientPlugins.values()),
@@ -261,5 +323,6 @@ export default connect(
clients, clients,
disabledPlugins, disabledPlugins,
failedPlugins, failedPlugins,
selectedDevice: selectedDevice?.serial,
}), }),
)(PluginDebugger); )(PluginDebugger);