From 780ac863b8230ed123dca973fa5933c734d2f689 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20B=C3=BCchele?= Date: Thu, 20 Dec 2018 06:07:55 -0800 Subject: [PATCH] Adding PluginDebugger sheet Summary: Adding a PluginDebugger that gives the user some information why a plugin might not be loaded. Reviewed By: jknoxville Differential Revision: D13465143 fbshipit-source-id: f5d7037850874ca9545ac1523fb4e0f18ede7273 --- src/App.js | 3 + src/chrome/PluginDebugger.js | 265 +++++++++++++++++++++++++++++++++++ 2 files changed, 268 insertions(+) create mode 100644 src/chrome/PluginDebugger.js diff --git a/src/App.js b/src/App.js index e1123b05f..543ad581e 100644 --- a/src/App.js +++ b/src/App.js @@ -16,6 +16,7 @@ import ErrorBar from './chrome/ErrorBar.js'; import PluginContainer from './PluginContainer.js'; import Sheet from './chrome/Sheet.js'; import {ipcRenderer} from 'electron'; +import PluginDebugger from './chrome/PluginDebugger.js'; import type Logger from './fb-stubs/Logger.js'; import type BugReporter from './fb-stubs/BugReporter.js'; @@ -55,6 +56,8 @@ export class App extends React.Component { onHide={onHide} /> ); + } else if (this.props.activeSheet === 'PLUGIN_DEBUGGER') { + return ; } else { return null; } diff --git a/src/chrome/PluginDebugger.js b/src/chrome/PluginDebugger.js new file mode 100644 index 000000000..8e5457082 --- /dev/null +++ b/src/chrome/PluginDebugger.js @@ -0,0 +1,265 @@ +/** + * Copyright 2018-present Facebook. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * @format + */ + +import type {FlipperDevicePlugin, FlipperPlugin} from '../plugin'; +import type {PluginDefinition} from '../dispatcher/plugins'; +import type Client from '../Client'; + +import {Component} from 'react'; +import {connect} from 'react-redux'; +import {FlexColumn, Button, Text, ManagedTable, styled, colors} from 'flipper'; +import {remote} from 'electron'; + +const Container = styled(FlexColumn)({ + padding: 10, + width: 700, +}); + +const InfoText = styled(Text)({ + lineHeight: '140%', +}); + +const Title = styled('div')({ + fontWeight: '500', + marginBottom: 10, + marginTop: 8, +}); + +const Ellipsis = styled(Text)({ + overflow: 'hidden', + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', +}); + +const Row = styled(FlexColumn)({ + alignItems: 'flex-end', +}); + +const TableContainer = styled('div')({ + borderRadius: 4, + overflow: 'hidden', + border: `1px solid ${colors.macOSTitleBarButtonBorder}`, + marginTop: 10, + marginBottom: 10, + backgroundColor: colors.white, + height: 400, + display: 'flex', +}); + +const Lamp = styled('div')(props => ({ + width: 10, + height: 10, + borderRadius: 5, + backgroundColor: props.on ? colors.lime : colors.red, + border: `1px solid ${colors.blackAlpha30}`, + marginTop: 6, + flexShrink: 0, +})); + +type Props = {| + devicePlugins: Array>, + clientPlugins: Array>, + gatekeepedPlugins: Array, + disabledPlugins: Array, + failedPlugins: Array<[PluginDefinition, string]>, + clients: Array, + onHide: () => mixed, +|}; + +const COLUMNS = { + lamp: { + value: '', + }, + name: { + value: 'Name', + }, + status: { + value: 'Status', + }, + gk: { + value: 'GK', + }, + clients: { + value: 'Supported by', + }, + source: { + value: 'Source', + }, +}; + +const COLUMNS_SIZES = { + lamp: 20, + name: 'flex', + status: 110, + gk: 120, + clients: 90, + source: 140, +}; + +class PluginDebugger extends Component { + buildRow( + name: string, + loaded: boolean, + status: string, + GKname: ?string, + GKpassing: ?boolean, + pluginPath: ?string, + ) { + return { + key: name, + columns: { + lamp: {value: }, + name: {value: {name}}, + status: { + value: status ? ( + + {status} + + ) : null, + }, + gk: { + value: GKname && ( + + {GKname} + + ), + }, + clients: { + value: this.getSupportedClients(name), + }, + source: { + value: + pluginPath && pluginPath.startsWith(remote.app.getAppPath()) ? ( + bundled + ) : ( + + {pluginPath} + + ), + }, + }, + }; + } + + getSupportedClients(id: string): string { + return this.props.clients + .reduce((acc: Array, cv: Client) => { + if (cv.plugins.includes(id)) { + acc.push(cv.query.app); + } + return acc; + }, []) + .join(', '); + } + + getRows() { + let rows = []; + this.props.gatekeepedPlugins.forEach(plugin => + rows.push( + this.buildRow( + plugin.name, + false, + 'GK disabled', + plugin.gatekeeper, + false, + plugin.entry, + ), + ), + ); + + this.props.devicePlugins.forEach(plugin => + rows.push( + this.buildRow( + plugin.id, + true, + '', + // $FlowFixMe: Flow doesn't know this is inherited from FlipperBasePlugin + plugin.gatekeeper, + true, + // $FlowFixMe: Flow doesn't know this is inherited from FlipperBasePlugin + plugin.entry, + ), + ), + ); + + this.props.clientPlugins.forEach(plugin => + rows.push( + this.buildRow( + plugin.id, + true, + '', + // $FlowFixMe: Flow doesn't know this is inherited from FlipperBasePlugin + plugin.gatekeeper, + true, + // $FlowFixMe: Flow doesn't know this is inherited from FlipperBasePlugin + plugin.entry, + ), + ), + ); + + this.props.disabledPlugins.forEach(plugin => + rows.push( + this.buildRow(plugin.name, false, 'disabled', null, null, plugin.entry), + ), + ); + + this.props.failedPlugins.forEach(([plugin, status]) => + rows.push( + this.buildRow(plugin.name, false, status, null, null, plugin.entry), + ), + ); + + return rows.sort((a, b) => (a.key < b.key ? -1 : 1)); + } + + render() { + return ( + + Plugin Status + + 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. + + + + + + + + + ); + } +} + +// $FlowFixMe +export default connect( + ({ + plugins: { + devicePlugins, + clientPlugins, + gatekeepedPlugins, + disabledPlugins, + failedPlugins, + }, + connections: {selectedPlugin, clients}, + }) => ({ + devicePlugins: Array.from(devicePlugins.values()), + clientPlugins: Array.from(clientPlugins.values()), + gatekeepedPlugins, + clients, + disabledPlugins, + failedPlugins, + }), +)(PluginDebugger);