Make sure plugin name selections are displayed consistently with sidebar, [Flipper] Make sure plugins have the same name everywhere
Summary: Not all plugin names are created equal in flipper. For example, plugins would bear different names in the sidebar and in the plugin selection when making a support request / flipper trace. Fixed this and also introduced a `getPluginTitle` utility that produces this name consistently. Plugin listview now also sort their items consitently with the sidebar. Probably also fixed an error in the flipper export screen, where a correct TS error was supressed. Reviewed By: jknoxville Differential Revision: D19499404 fbshipit-source-id: c5b23a170d41d96799eb7899e249f70778717d45
This commit is contained in:
committed by
Facebook Github Bot
parent
edd0e01a08
commit
82e65c68dc
@@ -18,33 +18,45 @@ import type {State as PluginMessageQueueState} from '../../reducers/pluginStates
|
||||
import {FlipperBasePlugin} from 'flipper';
|
||||
import type {ReduxState} from '../../reducers/index.tsx';
|
||||
|
||||
class MockFlipperPluginWithDefaultPersistedState extends FlipperBasePlugin<
|
||||
*,
|
||||
*,
|
||||
{msg: string},
|
||||
> {
|
||||
static defaultPersistedState = {msg: 'MockFlipperPluginWithPersistedState'};
|
||||
}
|
||||
|
||||
class MockFlipperPluginWithExportPersistedState extends FlipperBasePlugin<
|
||||
*,
|
||||
*,
|
||||
{msg: string},
|
||||
> {
|
||||
static exportPersistedState = (
|
||||
callClient: (string, ?Object) => Promise<Object>,
|
||||
persistedState: ?{msg: string},
|
||||
store: ?ReduxState,
|
||||
): Promise<?{msg: string}> => {
|
||||
return Promise.resolve({msg: 'MockFlipperPluginWithExportPersistedState'});
|
||||
function createMockFlipperPluginWithDefaultPersistedState(id: string) {
|
||||
return class MockFlipperPluginWithDefaultPersistedState extends FlipperBasePlugin<
|
||||
*,
|
||||
*,
|
||||
{msg: string},
|
||||
> {
|
||||
static id = id;
|
||||
static defaultPersistedState = {msg: 'MockFlipperPluginWithPersistedState'};
|
||||
};
|
||||
}
|
||||
|
||||
class MockFlipperPluginWithNoPersistedState extends FlipperBasePlugin<
|
||||
*,
|
||||
*,
|
||||
*,
|
||||
> {}
|
||||
function createMockFlipperPluginWithExportPersistedState(id: string) {
|
||||
return class MockFlipperPluginWithExportPersistedState extends FlipperBasePlugin<
|
||||
*,
|
||||
*,
|
||||
{msg: string},
|
||||
> {
|
||||
static id = id;
|
||||
static exportPersistedState = (
|
||||
callClient: (string, ?Object) => Promise<Object>,
|
||||
persistedState: ?{msg: string},
|
||||
store: ?ReduxState,
|
||||
): Promise<?{msg: string}> => {
|
||||
return Promise.resolve({
|
||||
msg: 'MockFlipperPluginWithExportPersistedState',
|
||||
});
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
function createMockFlipperPluginWithNoPersistedState(id: string) {
|
||||
return class MockFlipperPluginWithNoPersistedState extends FlipperBasePlugin<
|
||||
*,
|
||||
*,
|
||||
*,
|
||||
> {
|
||||
static id = id;
|
||||
};
|
||||
}
|
||||
|
||||
function mockPluginState(
|
||||
gatekeepedPlugins: Array<PluginDefinition>,
|
||||
@@ -53,12 +65,24 @@ function mockPluginState(
|
||||
): PluginsState {
|
||||
return {
|
||||
devicePlugins: new Map([
|
||||
['DevicePlugin1', MockFlipperPluginWithDefaultPersistedState],
|
||||
['DevicePlugin2', MockFlipperPluginWithDefaultPersistedState],
|
||||
[
|
||||
'DevicePlugin1',
|
||||
createMockFlipperPluginWithDefaultPersistedState('DevicePlugin1'),
|
||||
],
|
||||
[
|
||||
'DevicePlugin2',
|
||||
createMockFlipperPluginWithDefaultPersistedState('DevicePlugin2'),
|
||||
],
|
||||
]),
|
||||
clientPlugins: new Map([
|
||||
['ClientPlugin1', MockFlipperPluginWithDefaultPersistedState],
|
||||
['ClientPlugin2', MockFlipperPluginWithDefaultPersistedState],
|
||||
[
|
||||
'ClientPlugin1',
|
||||
createMockFlipperPluginWithDefaultPersistedState('ClientPlugin1'),
|
||||
],
|
||||
[
|
||||
'ClientPlugin2',
|
||||
createMockFlipperPluginWithDefaultPersistedState('ClientPlugin2'),
|
||||
],
|
||||
]),
|
||||
gatekeepedPlugins,
|
||||
disabledPlugins,
|
||||
@@ -98,12 +122,24 @@ test('getPersistentPlugins with no plugins getting excluded', () => {
|
||||
test('getPersistentPlugins, where the plugins with exportPersistedState not getting excluded', () => {
|
||||
const state: PluginsState = {
|
||||
devicePlugins: new Map([
|
||||
['DevicePlugin1', MockFlipperPluginWithExportPersistedState],
|
||||
['DevicePlugin2', MockFlipperPluginWithExportPersistedState],
|
||||
[
|
||||
'DevicePlugin1',
|
||||
createMockFlipperPluginWithExportPersistedState('DevicePlugin1'),
|
||||
],
|
||||
[
|
||||
'DevicePlugin2',
|
||||
createMockFlipperPluginWithExportPersistedState('DevicePlugin2'),
|
||||
],
|
||||
]),
|
||||
clientPlugins: new Map([
|
||||
['ClientPlugin1', MockFlipperPluginWithExportPersistedState],
|
||||
['ClientPlugin2', MockFlipperPluginWithExportPersistedState],
|
||||
[
|
||||
'ClientPlugin1',
|
||||
createMockFlipperPluginWithExportPersistedState('ClientPlugin1'),
|
||||
],
|
||||
[
|
||||
'ClientPlugin2',
|
||||
createMockFlipperPluginWithExportPersistedState('ClientPlugin2'),
|
||||
],
|
||||
]),
|
||||
gatekeepedPlugins: [],
|
||||
disabledPlugins: [],
|
||||
@@ -122,12 +158,24 @@ test('getPersistentPlugins, where the plugins with exportPersistedState not gett
|
||||
test('getPersistentPlugins, where the non persistent plugins getting excluded', () => {
|
||||
const state: PluginsState = {
|
||||
devicePlugins: new Map([
|
||||
['DevicePlugin1', MockFlipperPluginWithNoPersistedState],
|
||||
['DevicePlugin2', MockFlipperPluginWithDefaultPersistedState],
|
||||
[
|
||||
'DevicePlugin1',
|
||||
createMockFlipperPluginWithNoPersistedState('DevicePlugin1'),
|
||||
],
|
||||
[
|
||||
'DevicePlugin2',
|
||||
createMockFlipperPluginWithDefaultPersistedState('DevicePlugin2'),
|
||||
],
|
||||
]),
|
||||
clientPlugins: new Map([
|
||||
['ClientPlugin1', MockFlipperPluginWithDefaultPersistedState],
|
||||
['ClientPlugin2', MockFlipperPluginWithNoPersistedState],
|
||||
[
|
||||
'ClientPlugin1',
|
||||
createMockFlipperPluginWithDefaultPersistedState('ClientPlugin1'),
|
||||
],
|
||||
[
|
||||
'ClientPlugin2',
|
||||
createMockFlipperPluginWithNoPersistedState('ClientPlugin2'),
|
||||
],
|
||||
]),
|
||||
gatekeepedPlugins: [],
|
||||
disabledPlugins: [],
|
||||
@@ -141,12 +189,24 @@ test('getPersistentPlugins, where the non persistent plugins getting excluded',
|
||||
test('getActivePersistentPlugins, where the non persistent plugins getting excluded', () => {
|
||||
const state: PluginsState = {
|
||||
devicePlugins: new Map([
|
||||
['DevicePlugin1', MockFlipperPluginWithNoPersistedState],
|
||||
['DevicePlugin2', MockFlipperPluginWithDefaultPersistedState],
|
||||
[
|
||||
'DevicePlugin1',
|
||||
createMockFlipperPluginWithNoPersistedState('DevicePlugin1'),
|
||||
],
|
||||
[
|
||||
'DevicePlugin2',
|
||||
createMockFlipperPluginWithDefaultPersistedState('DevicePlugin2'),
|
||||
],
|
||||
]),
|
||||
clientPlugins: new Map([
|
||||
['ClientPlugin1', MockFlipperPluginWithDefaultPersistedState],
|
||||
['ClientPlugin2', MockFlipperPluginWithNoPersistedState],
|
||||
[
|
||||
'ClientPlugin1',
|
||||
createMockFlipperPluginWithDefaultPersistedState('ClientPlugin1'),
|
||||
],
|
||||
[
|
||||
'ClientPlugin2',
|
||||
createMockFlipperPluginWithNoPersistedState('ClientPlugin2'),
|
||||
],
|
||||
]),
|
||||
gatekeepedPlugins: [],
|
||||
disabledPlugins: [],
|
||||
@@ -161,19 +221,43 @@ test('getActivePersistentPlugins, where the non persistent plugins getting exclu
|
||||
};
|
||||
const queues: PluginMessageQueueState = {};
|
||||
const list = getActivePersistentPlugins(plugins, queues, state);
|
||||
expect(list).toEqual(['ClientPlugin1', 'DevicePlugin2']);
|
||||
expect(list).toEqual([
|
||||
{
|
||||
id: 'ClientPlugin1',
|
||||
label: 'ClientPlugin1',
|
||||
},
|
||||
{
|
||||
id: 'DevicePlugin2',
|
||||
label: 'DevicePlugin2',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
test('getActivePersistentPlugins, where the plugins not in pluginState or queue gets excluded', () => {
|
||||
const state: PluginsState = {
|
||||
devicePlugins: new Map([
|
||||
['DevicePlugin1', MockFlipperPluginWithDefaultPersistedState],
|
||||
['DevicePlugin2', MockFlipperPluginWithDefaultPersistedState],
|
||||
[
|
||||
'DevicePlugin1',
|
||||
createMockFlipperPluginWithDefaultPersistedState('DevicePlugin1'),
|
||||
],
|
||||
[
|
||||
'DevicePlugin2',
|
||||
createMockFlipperPluginWithDefaultPersistedState('DevicePlugin2'),
|
||||
],
|
||||
]),
|
||||
clientPlugins: new Map([
|
||||
['ClientPlugin1', MockFlipperPluginWithDefaultPersistedState],
|
||||
['ClientPlugin2', MockFlipperPluginWithDefaultPersistedState],
|
||||
['ClientPlugin3', MockFlipperPluginWithDefaultPersistedState],
|
||||
[
|
||||
'ClientPlugin1',
|
||||
createMockFlipperPluginWithDefaultPersistedState('ClientPlugin1'),
|
||||
],
|
||||
[
|
||||
'ClientPlugin2',
|
||||
createMockFlipperPluginWithDefaultPersistedState('ClientPlugin2'),
|
||||
],
|
||||
[
|
||||
'ClientPlugin3',
|
||||
createMockFlipperPluginWithDefaultPersistedState('ClientPlugin3'),
|
||||
],
|
||||
]),
|
||||
gatekeepedPlugins: [],
|
||||
disabledPlugins: [],
|
||||
@@ -190,5 +274,18 @@ test('getActivePersistentPlugins, where the plugins not in pluginState or queue
|
||||
],
|
||||
};
|
||||
const list = getActivePersistentPlugins(plugins, queues, state);
|
||||
expect(list).toEqual(['ClientPlugin2', 'ClientPlugin3', 'DevicePlugin1']);
|
||||
expect(list).toEqual([
|
||||
{
|
||||
id: 'ClientPlugin2',
|
||||
label: 'ClientPlugin2',
|
||||
},
|
||||
{
|
||||
id: 'ClientPlugin3',
|
||||
label: 'ClientPlugin3',
|
||||
},
|
||||
{
|
||||
id: 'DevicePlugin1',
|
||||
label: 'DevicePlugin1',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -42,6 +42,7 @@ import {setSelectPluginsToExportActiveSheet} from '../reducers/application';
|
||||
import {deconstructClientId, deconstructPluginKey} from '../utils/clientUtils';
|
||||
import {performance} from 'perf_hooks';
|
||||
import {processMessageQueue} from './messageQueue';
|
||||
import {getPluginTitle} from './pluginUtils';
|
||||
|
||||
export const IMPORT_FLIPPER_TRACE_EVENT = 'import-flipper-trace';
|
||||
export const EXPORT_FLIPPER_TRACE_EVENT = 'export-flipper-trace';
|
||||
@@ -85,7 +86,8 @@ type SerializePluginStatesOptions = {
|
||||
|
||||
type PluginsToProcess = {
|
||||
pluginKey: string;
|
||||
plugin: string;
|
||||
pluginId: string;
|
||||
pluginName: string;
|
||||
pluginClass: typeof FlipperPlugin | typeof FlipperDevicePlugin;
|
||||
client: Client;
|
||||
}[];
|
||||
@@ -398,33 +400,39 @@ export async function fetchMetadata(
|
||||
const newPluginState = {...pluginStates};
|
||||
const errorArray: Array<Error> = [];
|
||||
|
||||
for (const {plugin, pluginClass, client, pluginKey} of pluginsToProcess) {
|
||||
for (const {
|
||||
pluginName,
|
||||
pluginId,
|
||||
pluginClass,
|
||||
client,
|
||||
pluginKey,
|
||||
} of pluginsToProcess) {
|
||||
const exportState = pluginClass ? pluginClass.exportPersistedState : null;
|
||||
if (exportState) {
|
||||
const fetchMetaDataMarker = `${EXPORT_FLIPPER_TRACE_EVENT}:fetch-meta-data-per-plugin`;
|
||||
performance.mark(fetchMetaDataMarker);
|
||||
try {
|
||||
statusUpdate &&
|
||||
statusUpdate(`Fetching metadata for plugin ${plugin}...`);
|
||||
statusUpdate(`Fetching metadata for plugin ${pluginName}...`);
|
||||
const data = await promiseTimeout(
|
||||
240000, // Fetching MobileConfig data takes ~ 3 mins, thus keeping timeout at 4 mins.
|
||||
exportState(
|
||||
callClient(client, plugin),
|
||||
callClient(client, pluginId),
|
||||
newPluginState[pluginKey],
|
||||
state,
|
||||
idler,
|
||||
statusUpdate,
|
||||
),
|
||||
`Timed out while collecting data for ${plugin}`,
|
||||
`Timed out while collecting data for ${pluginName}`,
|
||||
);
|
||||
getLogger().trackTimeSince(fetchMetaDataMarker, fetchMetaDataMarker, {
|
||||
plugin,
|
||||
pluginId,
|
||||
});
|
||||
newPluginState[pluginKey] = data;
|
||||
} catch (e) {
|
||||
errorArray.push(e);
|
||||
getLogger().trackTimeSince(fetchMetaDataMarker, fetchMetaDataMarker, {
|
||||
plugin,
|
||||
pluginId,
|
||||
error: e,
|
||||
});
|
||||
continue;
|
||||
@@ -441,7 +449,12 @@ async function processQueues(
|
||||
statusUpdate?: (msg: string) => void,
|
||||
idler?: Idler,
|
||||
) {
|
||||
for (const {plugin, pluginKey, pluginClass} of pluginsToProcess) {
|
||||
for (const {
|
||||
pluginName,
|
||||
pluginId,
|
||||
pluginKey,
|
||||
pluginClass,
|
||||
} of pluginsToProcess) {
|
||||
if (pluginClass.persistedStateReducer) {
|
||||
const processQueueMarker = `${EXPORT_FLIPPER_TRACE_EVENT}:process-queue-per-plugin`;
|
||||
performance.mark(processQueueMarker);
|
||||
@@ -454,14 +467,14 @@ async function processQueues(
|
||||
statusUpdate?.(
|
||||
`Processing event ${current} / ${total} (${Math.round(
|
||||
(current / total) * 100,
|
||||
)}%) for plugin ${plugin}`,
|
||||
)}%) for plugin ${pluginName}`,
|
||||
);
|
||||
},
|
||||
idler,
|
||||
);
|
||||
|
||||
getLogger().trackTimeSince(processQueueMarker, processQueueMarker, {
|
||||
plugin,
|
||||
pluginId,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -506,7 +519,8 @@ export function determinePluginsToProcess(
|
||||
pluginsToProcess.push({
|
||||
pluginKey: key,
|
||||
client,
|
||||
plugin,
|
||||
pluginId: plugin,
|
||||
pluginName: getPluginTitle(pluginClass),
|
||||
pluginClass,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -77,38 +77,46 @@ export function getActivePersistentPlugins(
|
||||
pluginsMessageQueue: PluginMessageQueueState,
|
||||
plugins: PluginsState,
|
||||
selectedClient?: Client,
|
||||
): Array<string> {
|
||||
): {id: string; label: string}[] {
|
||||
const pluginsMap: Map<
|
||||
string,
|
||||
typeof FlipperDevicePlugin | typeof FlipperPlugin
|
||||
> = pluginsClassMap(plugins);
|
||||
return getPersistentPlugins(plugins).filter(plugin => {
|
||||
const pluginClass = pluginsMap.get(plugin);
|
||||
const keys = [
|
||||
...new Set([
|
||||
...Object.keys(pluginsState),
|
||||
...Object.keys(pluginsMessageQueue),
|
||||
]),
|
||||
]
|
||||
.filter(k => !selectedClient || k.includes(selectedClient.id))
|
||||
.map(key => deconstructPluginKey(key).pluginName);
|
||||
let result = plugin == 'DeviceLogs';
|
||||
const pluginsWithExportPersistedState =
|
||||
pluginClass && pluginClass.exportPersistedState != undefined;
|
||||
const pluginsWithReduxData = keys.includes(plugin);
|
||||
if (!result && selectedClient) {
|
||||
// If there is a selected client, active persistent plugin is the plugin which is active for selectedClient and also persistent.
|
||||
result =
|
||||
selectedClient.plugins.includes(plugin) &&
|
||||
(pluginsWithExportPersistedState || pluginsWithReduxData);
|
||||
} else if (!result && !selectedClient) {
|
||||
// If there is no selected client, active persistent plugin is the plugin which is just persistent.
|
||||
result =
|
||||
(pluginClass && pluginClass.exportPersistedState != undefined) ||
|
||||
keys.includes(plugin);
|
||||
}
|
||||
return result;
|
||||
});
|
||||
return getPersistentPlugins(plugins)
|
||||
.map(pluginName => pluginsMap.get(pluginName)!)
|
||||
.sort(sortPluginsByName)
|
||||
.map(plugin => {
|
||||
const keys = [
|
||||
...new Set([
|
||||
...Object.keys(pluginsState),
|
||||
...Object.keys(pluginsMessageQueue),
|
||||
]),
|
||||
]
|
||||
.filter(k => !selectedClient || k.includes(selectedClient.id))
|
||||
.map(key => deconstructPluginKey(key).pluginName);
|
||||
let result = plugin.id == 'DeviceLogs';
|
||||
const pluginsWithExportPersistedState =
|
||||
plugin && plugin.exportPersistedState != undefined;
|
||||
const pluginsWithReduxData = keys.includes(plugin.id);
|
||||
if (!result && selectedClient) {
|
||||
// If there is a selected client, active persistent plugin is the plugin which is active for selectedClient and also persistent.
|
||||
result =
|
||||
selectedClient.plugins.includes(plugin.id) &&
|
||||
(pluginsWithExportPersistedState || pluginsWithReduxData);
|
||||
} else if (!result && !selectedClient) {
|
||||
// If there is no selected client, active persistent plugin is the plugin which is just persistent.
|
||||
result =
|
||||
(plugin && plugin.exportPersistedState != undefined) ||
|
||||
keys.includes(plugin.id);
|
||||
}
|
||||
return (result
|
||||
? {
|
||||
id: plugin.id,
|
||||
label: getPluginTitle(plugin),
|
||||
}
|
||||
: undefined)!;
|
||||
})
|
||||
.filter(Boolean);
|
||||
}
|
||||
|
||||
export function getPersistentPlugins(plugins: PluginsState): Array<string> {
|
||||
@@ -144,3 +152,27 @@ export function getPersistentPlugins(plugins: PluginsState): Array<string> {
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export function getPluginTitle(pluginClass: typeof FlipperBasePlugin) {
|
||||
return pluginClass.title || pluginClass.id;
|
||||
}
|
||||
|
||||
export function sortPluginsByName(
|
||||
a: typeof FlipperBasePlugin,
|
||||
b: typeof FlipperBasePlugin,
|
||||
): number {
|
||||
// make sure Device plugins are sorted before normal plugins
|
||||
if (
|
||||
a.prototype instanceof FlipperDevicePlugin &&
|
||||
!(b.prototype instanceof FlipperDevicePlugin)
|
||||
) {
|
||||
return -1;
|
||||
}
|
||||
if (
|
||||
b.prototype instanceof FlipperDevicePlugin &&
|
||||
!(a.prototype instanceof FlipperDevicePlugin)
|
||||
) {
|
||||
return 1;
|
||||
}
|
||||
return getPluginTitle(a) > getPluginTitle(b) ? 1 : -1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user