"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
This commit is contained in:
Anton Nikolaev
2020-12-15 09:28:58 -08:00
committed by Facebook GitHub Bot
parent f3e1a48ff3
commit 9c5f59e109
2 changed files with 110 additions and 43 deletions

View File

@@ -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({
))}
</PluginGroup>
)}
<PluginGroup
key="uninstalled"
title="Detected in App"
hint="The plugins below are supported by the selected device / application, but not installed in Flipper.">
{uninstalledPlugins.map((plugin) => (
<PluginEntry
key={plugin.id}
plugin={plugin}
scrollTo={plugin.id === connections.selectedPlugin}
tooltip={getPluginTooltip(plugin)}
disabled
/>
))}
</PluginGroup>
{!isArchived && (
<PluginGroup
key="unavailable"
@@ -371,6 +387,7 @@ export function computePluginLists(
const enabledPlugins: ClientPluginDefinition[] = [];
const disabledPlugins: ClientPluginDefinition[] = [];
const unavailablePlugins: [plugin: PluginDetails, reason: string][] = [];
const uninstalledPlugins: DownloadablePluginDetails[] = [];
if (device) {
// find all device plugins that aren't part of the current device / metro
@@ -390,36 +407,6 @@ 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,
);
client &&
clientPlugins.forEach((plugin) => {
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<string>([
...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,
};
}

View File

@@ -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(