From 6ffc027051adbb0f6351bf903fd32dad90ce4d56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20B=C3=BCchele?= Date: Tue, 18 Dec 2018 08:27:25 -0800 Subject: [PATCH] read infos from package.json Summary: Adding the properties from a plugin's `package.json` as static properties to the class. The name from `package.json` is used as it's `id`. This allows us in the future to add meta information about a plugin to it's package.json and still use the data inside the app. Reviewed By: priteshrnandgaonkar Differential Revision: D13417288 fbshipit-source-id: 3d0a62d4cb0115153cce1aaee677b9680fefebf4 --- src/NotificationsHub.js | 2 +- src/PluginContainer.js | 5 ++--- src/__tests__/createTablePlugin.node.js | 21 -------------------- src/chrome/MainSidebar.js | 10 +++++++--- src/createTablePlugin.js | 12 +++-------- src/dispatcher/__tests__/TestPlugin.js | 4 +++- src/dispatcher/__tests__/plugins.electron.js | 15 ++++++++++---- src/dispatcher/plugins.js | 20 ++++++++++++++++++- src/plugin.js | 12 +++++++---- 9 files changed, 54 insertions(+), 47 deletions(-) diff --git a/src/NotificationsHub.js b/src/NotificationsHub.js index 04aba1192..40acf7855 100644 --- a/src/NotificationsHub.js +++ b/src/NotificationsHub.js @@ -472,7 +472,7 @@ class NotificationItem extends Component { const items = []; if (props.onHidePlugin && props.plugin) { items.push({ - label: `Hide ${props.plugin.title} plugin`, + label: `Hide ${props.plugin.title || props.plugin.id} plugin`, click: this.props.onHidePlugin, }); } diff --git a/src/PluginContainer.js b/src/PluginContainer.js index 9d7d9632e..063880daa 100644 --- a/src/PluginContainer.js +++ b/src/PluginContainer.js @@ -120,9 +120,8 @@ class PluginContainer extends PureComponent { {React.createElement(activePlugin, props)} diff --git a/src/__tests__/createTablePlugin.node.js b/src/__tests__/createTablePlugin.node.js index fe61ec91e..bc1150967 100644 --- a/src/__tests__/createTablePlugin.node.js +++ b/src/__tests__/createTablePlugin.node.js @@ -9,9 +9,6 @@ import {createTablePlugin} from '../createTablePlugin.js'; import {FlipperPlugin} from '../plugin.js'; const PROPS = { - title: 'Plugin Title', - id: 'pluginID', - icon: 'icon', method: 'method', resetMethod: 'resetMethod', columns: {}, @@ -25,24 +22,6 @@ test('createTablePlugin returns FlipperPlugin', () => { expect(tablePlugin.prototype).toBeInstanceOf(FlipperPlugin); }); -test('Plugin ID is set', () => { - const id = 'pluginID'; - const tablePlugin = createTablePlugin({...PROPS, id}); - expect(tablePlugin.id).toBe(id); -}); - -test('Plugin title is set', () => { - const title = 'My Plugin Title'; - const tablePlugin = createTablePlugin({...PROPS, title}); - expect(tablePlugin.title).toBe(title); -}); - -test('Plugin icon is set', () => { - const icon = 'icon'; - const tablePlugin = createTablePlugin({...PROPS, icon}); - expect(tablePlugin.icon).toBe(icon); -}); - test('persistedStateReducer is resetting data', () => { const resetMethod = 'resetMethod'; const tablePlugin = createTablePlugin({...PROPS, resetMethod}); diff --git a/src/chrome/MainSidebar.js b/src/chrome/MainSidebar.js index 80d5a1757..35bf2f6db 100644 --- a/src/chrome/MainSidebar.js +++ b/src/chrome/MainSidebar.js @@ -146,11 +146,11 @@ class PluginSidebarListItem extends Component<{ - {plugin.title} + {plugin.title || plugin.id} ); } @@ -228,7 +228,11 @@ class MainSidebar extends PureComponent { }> 0 ? NotificationsHub.icon : 'bell-null'} + name={ + numNotifications > 0 + ? NotificationsHub.icon || 'bell' + : 'bell-null' + } isActive={selectedPlugin === NotificationsHub.id} /> = {| - title: string, - id: string, - icon: string, +type Props = { method: string, resetMethod?: string, columns: TableColumns, columnSizes: TableColumnSizes, renderSidebar: (row: T) => any, buildRow: (row: T) => any, -|}; +}; type PersistedState = {| rows: TableRows, @@ -59,9 +56,6 @@ type State = {| export function createTablePlugin(props: Props) { // $FlowFixMe persistedStateReducer is fine to accept payload of type T, because it is of type RowData return class extends FlipperPlugin> { - static title = props.title; - static id = props.id; - static icon = props.icon; static keyboardActions = ['clear', 'createPaste']; static defaultPersistedState: PersistedState = { @@ -170,7 +164,7 @@ export function createTablePlugin(props: Props) { return ( { }); test('requirePlugin loads plugin', () => { + const name = 'pluginID'; + const homepage = 'https://fb.workplace.com/groups/230455004101832/'; const plugin = requirePlugin(require)({ - name: 'pluginID', + name, + homepage, out: path.join(__dirname, 'TestPlugin.js'), - // $FlowFixMe Electron require returns default exports wrapped in an object - }).default; - + }); + // $FlowFixMe expect(plugin.prototype).toBeInstanceOf(FlipperPlugin); + // $FlowFixMe + expect(plugin.homepage).toBe(homepage); + // $FlowFixMe + expect(plugin.id).toBe(TestPlugin.id); }); diff --git a/src/dispatcher/plugins.js b/src/dispatcher/plugins.js index ebf0516ef..5eaa025bd 100644 --- a/src/dispatcher/plugins.js +++ b/src/dispatcher/plugins.js @@ -32,6 +32,7 @@ export default (store: Store, logger: Logger) => { window.Flipper = Flipper; const disabled = checkDisabled(); + const initialPlugins: Array< Class | FlipperDevicePlugin<>>, > = [...getBundledPlugins(), ...getDynamicPlugins()] @@ -113,10 +114,27 @@ export function requirePlugin( pluginDefinition: PluginDefinition, ): ?Class | FlipperDevicePlugin<>> => { try { - const plugin = requireFunction(pluginDefinition.out); + let plugin = requireFunction(pluginDefinition.out); + if (plugin.default) { + plugin = plugin.default; + } if (!plugin.prototype instanceof FlipperBasePlugin) { throw new Error(`Plugin ${plugin.name} is not a FlipperBasePlugin`); } + + // set values from package.json as static variables on class + Object.keys(pluginDefinition).forEach(key => { + if (key === 'name') { + plugin.id = plugin.id || pluginDefinition.name; + } else if (key === 'id') { + throw new Error( + 'Field "id" not allowed in package.json. The plugin\'s name will be used as ID"', + ); + } else { + plugin[key] = plugin[key] || pluginDefinition[key]; + } + }); + return plugin; } catch (e) { console.error(pluginDefinition, e); diff --git a/src/plugin.js b/src/plugin.js index 3e803a7cd..ef2a16960 100644 --- a/src/plugin.js +++ b/src/plugin.js @@ -49,9 +49,13 @@ export class FlipperBasePlugin< Actions = *, PersistedState = *, > extends React.Component, State> { - static title: string = 'Unknown'; - static id: string = 'Unknown'; - static icon: string = 'apps'; + static title: ?string = null; + static id: string = ''; + static icon: ?string = null; + static bugs: ?{ + email?: string, + url?: string, + } = null; static keyboardActions: ?KeyboardActions; static screenshot: ?string; static defaultPersistedState: PersistedState; @@ -78,7 +82,7 @@ export class FlipperBasePlugin< onKeyboardAction: ?(action: string) => void; toJSON() { - return `<${this.constructor.name}#${this.constructor.title}>`; + return `<${this.constructor.name}#${this.constructor.id}>`; } // methods to be overriden by plugins