From 9c5f59e1091824b72e391ee31d851eaf9e732126 Mon Sep 17 00:00:00 2001 From: Anton Nikolaev Date: Tue, 15 Dec 2020 09:28:58 -0800 Subject: [PATCH] "Detected in App" section added to sidebar Summary: New section "Detected in App" in the main sidebar showing plugins which are supported by the currently selected client app, but not installed in Flipper. Note that in this diff we only show them, there is no "install" button yet. I will add it in a next diff. Reviewed By: mweststrate Differential Revision: D25361915 fbshipit-source-id: 8fff6887a8ec04b3b59c939a758c8f801f42490f --- .../sandy-chrome/appinspect/PluginList.tsx | 98 +++++++++++++------ .../appinspect/__tests__/PluginList.spec.tsx | 55 ++++++++--- 2 files changed, 110 insertions(+), 43 deletions(-) diff --git a/desktop/app/src/sandy-chrome/appinspect/PluginList.tsx b/desktop/app/src/sandy-chrome/appinspect/PluginList.tsx index e8b3c1f42..4cec4b76d 100644 --- a/desktop/app/src/sandy-chrome/appinspect/PluginList.tsx +++ b/desktop/app/src/sandy-chrome/appinspect/PluginList.tsx @@ -24,6 +24,7 @@ import {getFavoritePlugins} from '../../chrome/mainsidebar/sidebarUtils'; import {PluginDetails} from 'flipper-plugin-lib'; import {useMemoize} from '../../utils/useMemoize'; import MetroDevice from '../../devices/MetroDevice'; +import {DownloadablePluginDetails} from 'plugin-lib/lib'; const {SubMenu} = Menu; const {Text} = Typography; @@ -47,6 +48,7 @@ export const PluginList = memo(function PluginList({ enabledPlugins, disabledPlugins, unavailablePlugins, + uninstalledPlugins, } = useMemoize(computePluginLists, [ activeDevice, metroDevice, @@ -192,6 +194,20 @@ export const PluginList = memo(function PluginList({ ))} )} + + {uninstalledPlugins.map((plugin) => ( + + ))} + {!isArchived && ( { - if (!client.plugins.includes(plugin.id)) { - unavailablePlugins.push([ - plugin.details, - `Plugin '${getPluginTitle( - plugin.details, - )}' is not loaded by the client application`, - ]); - } else if (favoritePlugins.includes(plugin)) { - enabledPlugins.push(plugin); - } else { - disabledPlugins.push(plugin); - } - }); - } - // process problematic plugins plugins.disabledPlugins.forEach((plugin) => { unavailablePlugins.push([plugin, 'Plugin is disabled by configuration']); @@ -437,11 +424,61 @@ export function computePluginLists( ]); }); + // process all client plugins + if (device && client) { + const clientPlugins = Array.from(plugins.clientPlugins.values()).sort( + sortPluginsByName, + ); + const favoritePlugins = getFavoritePlugins( + device, + client, + clientPlugins, + client && userStarredPlugins[client.query.app], + true, + ); + clientPlugins.forEach((plugin) => { + if (!client.supportsPlugin(plugin.id)) { + unavailablePlugins.push([ + plugin.details, + `Plugin '${getPluginTitle( + plugin.details, + )}' is installed in Flipper, but not supported by the client application`, + ]); + } else if (favoritePlugins.includes(plugin)) { + enabledPlugins.push(plugin); + } else { + disabledPlugins.push(plugin); + } + }); + const installedPluginIds = new Set([ + ...clientPlugins.map((p) => p.id), + ...unavailablePlugins.map(([p]) => p.id), + ]); + const uninstalledMarketplacePlugins = plugins.marketplacePlugins.filter( + (p) => !installedPluginIds.has(p.id), + ); + uninstalledMarketplacePlugins.forEach((plugin) => { + if (client.supportsPlugin(plugin.id)) { + uninstalledPlugins.push(plugin); + } else { + unavailablePlugins.push([ + plugin, + `Plugin '${getPluginTitle( + plugin, + )}' is not installed in Flipper and not supported by the client application`, + ]); + } + }); + } + devicePlugins.sort(sortPluginsByName); metroPlugins.sort(sortPluginsByName); unavailablePlugins.sort(([a], [b]) => { return getPluginTitle(a) > getPluginTitle(b) ? 1 : -1; }); + uninstalledPlugins.sort((a, b) => { + return getPluginTitle(a) > getPluginTitle(b) ? 1 : -1; + }); return { devicePlugins, @@ -449,6 +486,7 @@ export function computePluginLists( enabledPlugins, disabledPlugins, unavailablePlugins, + uninstalledPlugins, }; } diff --git a/desktop/app/src/sandy-chrome/appinspect/__tests__/PluginList.spec.tsx b/desktop/app/src/sandy-chrome/appinspect/__tests__/PluginList.spec.tsx index bdcb8ebff..a7484d12d 100644 --- a/desktop/app/src/sandy-chrome/appinspect/__tests__/PluginList.spec.tsx +++ b/desktop/app/src/sandy-chrome/appinspect/__tests__/PluginList.spec.tsx @@ -20,10 +20,15 @@ import {_SandyPluginDefinition} from 'flipper-plugin'; import {createMockPluginDetails} from 'flipper-plugin/src/test-utils/test-utils'; import {selectPlugin, starPlugin} from '../../../reducers/connections'; import {registerMetroDevice} from '../../../dispatcher/metroDevice'; -import {addGatekeepedPlugins, registerPlugins} from '../../../reducers/plugins'; +import { + addGatekeepedPlugins, + registerMarketplacePlugins, + registerPlugins, +} from '../../../reducers/plugins'; // eslint-disable-next-line import * as LogsPluginModule from '../../../../../plugins/logs/index'; +import {createMockDownloadablePluginDetails} from '../../../utils/testUtils'; const logsPlugin = new _SandyPluginDefinition( createMockPluginDetails({id: 'DeviceLogs'}), @@ -163,6 +168,7 @@ describe('basic findBestDevice with metro present', () => { state.connections.userStarredPlugins, ), ).toEqual({ + uninstalledPlugins: [], devicePlugins: [logsPlugin], metroPlugins: [logsPlugin], enabledPlugins: [], @@ -196,7 +202,6 @@ describe('basic findBestDevice with metro present', () => { }, }, ); - const unsupportedPlugin = new _SandyPluginDefinition( createMockPluginDetails({ id: 'unsupportedPlugin', @@ -232,6 +237,16 @@ describe('basic findBestDevice with metro present', () => { noopPlugin, ); + const supportedUninstalledPlugin = createMockDownloadablePluginDetails({ + id: 'supportedUninstalledPlugin', + title: 'Supported Uninstalled Plugin', + }); + + const unsupportedUninstalledPlugin = createMockDownloadablePluginDetails({ + id: 'unsupportedUninstalledPlugin', + title: 'Unsupported Uninstalled Plugin', + }); + flipper.store.dispatch( registerPlugins([ unsupportedDevicePlugin, @@ -241,20 +256,29 @@ describe('basic findBestDevice with metro present', () => { ]), ); flipper.store.dispatch(addGatekeepedPlugins([gateKeepedPlugin])); + flipper.store.dispatch( + registerMarketplacePlugins([ + supportedUninstalledPlugin, + unsupportedUninstalledPlugin, + ]), + ); // ok, this is a little hackish - flipper.client.plugins = ['plugin1', 'plugin2']; + flipper.client.plugins = [ + 'plugin1', + 'plugin2', + 'supportedUninstalledPlugin', + ]; let state = flipper.store.getState(); - expect( - computePluginLists( - testDevice, - metro, - flipper.client, - state.plugins, - state.connections.userStarredPlugins, - ), - ).toEqual({ + const pluginLists = computePluginLists( + testDevice, + metro, + flipper.client, + state.plugins, + state.connections.userStarredPlugins, + ); + expect(pluginLists).toEqual({ devicePlugins: [logsPlugin], metroPlugins: [logsPlugin], enabledPlugins: [], @@ -270,9 +294,14 @@ describe('basic findBestDevice with metro present', () => { ], [ unsupportedPlugin.details, - "Plugin 'Unsupported Plugin' is not loaded by the client application", + "Plugin 'Unsupported Plugin' is installed in Flipper, but not supported by the client application", + ], + [ + unsupportedUninstalledPlugin, + "Plugin 'Unsupported Uninstalled Plugin' is not installed in Flipper and not supported by the client application", ], ], + uninstalledPlugins: [supportedUninstalledPlugin], }); flipper.store.dispatch(