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:
Michel Weststrate
2020-01-27 07:20:53 -08:00
committed by Facebook Github Bot
parent edd0e01a08
commit 82e65c68dc
12 changed files with 253 additions and 111 deletions

View File

@@ -34,6 +34,7 @@ import {selectPlugin} from './reducers/connections';
import {State as StoreState} from './reducers/index'; import {State as StoreState} from './reducers/index';
import textContent from './utils/textContent'; import textContent from './utils/textContent';
import createPaste from './fb-stubs/createPaste'; import createPaste from './fb-stubs/createPaste';
import {getPluginTitle} from './utils/pluginUtils';
type OwnProps = { type OwnProps = {
onClear: () => void; onClear: () => void;
@@ -429,7 +430,7 @@ class NotificationItem extends Component<
const items = []; const items = [];
if (props.onHidePlugin && props.plugin) { if (props.onHidePlugin && props.plugin) {
items.push({ items.push({
label: `Hide ${props.plugin.title || props.plugin.id} plugin`, label: `Hide ${getPluginTitle(props.plugin)} plugin`,
click: this.props.onHidePlugin, click: this.props.onHidePlugin,
}); });
} }
@@ -534,7 +535,7 @@ class NotificationItem extends Component<
<FlexRow> <FlexRow>
{action && ( {action && (
<Button onClick={this.openDeeplink}> <Button onClick={this.openDeeplink}>
Open in {plugin.title} Open in {getPluginTitle(plugin)}
</Button> </Button>
)} )}
<ButtonGroup> <ButtonGroup>
@@ -543,7 +544,7 @@ class NotificationItem extends Component<
)} )}
{onHidePlugin && ( {onHidePlugin && (
<Button onClick={onHidePlugin}> <Button onClick={onHidePlugin}>
Hide {plugin.title} Hide {getPluginTitle(plugin)}
</Button> </Button>
)} )}
</ButtonGroup> </ButtonGroup>

View File

@@ -58,12 +58,12 @@ const Container = styled(FlexColumn)({
}); });
type State = { type State = {
availablePluginsToExport: Array<string>; availablePluginsToExport: Array<{id: string; label: string}>;
}; };
class ExportDataPluginSheet extends Component<Props, State> { class ExportDataPluginSheet extends Component<Props, State> {
state: State = {availablePluginsToExport: []}; state: State = {availablePluginsToExport: []};
static getDerivedStateFromProps(props: Props, _state: State) { static getDerivedStateFromProps(props: Props, _state: State): State {
const {plugins, pluginStates, pluginMessageQueue, selectedClient} = props; const {plugins, pluginStates, pluginMessageQueue, selectedClient} = props;
const availablePluginsToExport = getActivePersistentPlugins( const availablePluginsToExport = getActivePersistentPlugins(
pluginStates, pluginStates,

View File

@@ -37,7 +37,7 @@ type Props = {
onSubmit?: () => void; onSubmit?: () => void;
onChange: (elements: Array<string>) => void; onChange: (elements: Array<string>) => void;
onHide: () => any; onHide: () => any;
elements: Array<string>; elements: Array<{label: string; id: string}>;
title?: string; title?: string;
} & SubType; } & SubType;
@@ -80,14 +80,15 @@ const Padder = styled.div<{
})); }));
type RowComponentProps = { type RowComponentProps = {
name: string; id: string;
label: string;
selected: boolean; selected: boolean;
onChange: (name: string, selected: boolean) => void; onChange: (name: string, selected: boolean) => void;
}; };
class RowComponent extends Component<RowComponentProps> { class RowComponent extends Component<RowComponentProps> {
render() { render() {
const {name, selected, onChange} = this.props; const {id, label, selected, onChange} = this.props;
return ( return (
<FlexColumn> <FlexColumn>
<Padder <Padder
@@ -96,12 +97,12 @@ class RowComponent extends Component<RowComponentProps> {
paddingBottom={8} paddingBottom={8}
paddingLeft={8}> paddingLeft={8}>
<FlexRow> <FlexRow>
<Text> {name} </Text> <Text> {label} </Text>
<Spacer /> <Spacer />
<Checkbox <Checkbox
checked={selected} checked={selected}
onChange={selected => { onChange={selected => {
onChange(name, selected); onChange(id, selected);
}} }}
/> />
</FlexRow> </FlexRow>
@@ -151,10 +152,11 @@ export default class ListView extends Component<Props, State> {
<FlexColumn> <FlexColumn>
{this.props.title && <Title>{this.props.title}</Title>} {this.props.title && <Title>{this.props.title}</Title>}
<RowComponentContainer> <RowComponentContainer>
{this.props.elements.map(id => { {this.props.elements.map(({id, label}) => {
return ( return (
<RowComponent <RowComponent
name={id} id={id}
label={label}
key={id} key={id}
selected={this.state.selectedElements.has(id)} selected={this.state.selectedElements.has(id)}
onChange={this.handleChange} onChange={this.handleChange}

View File

@@ -10,7 +10,7 @@
import BaseDevice from '../../devices/BaseDevice'; import BaseDevice from '../../devices/BaseDevice';
import Client from '../../Client'; import Client from '../../Client';
import {UninitializedClient} from '../../UninitializedClient'; import {UninitializedClient} from '../../UninitializedClient';
import {sortPluginsByName} from '../../plugin'; import {sortPluginsByName} from '../../utils/pluginUtils';
import {PluginNotification} from '../../reducers/notifications'; import {PluginNotification} from '../../reducers/notifications';
import {ActiveSheet} from '../../reducers/application'; import {ActiveSheet} from '../../reducers/application';
import {State as Store} from '../../reducers'; import {State as Store} from '../../reducers';

View File

@@ -10,7 +10,7 @@
import BaseDevice from '../../devices/BaseDevice'; import BaseDevice from '../../devices/BaseDevice';
import Client from '../../Client'; import Client from '../../Client';
import {UninitializedClient} from '../../UninitializedClient'; import {UninitializedClient} from '../../UninitializedClient';
import {sortPluginsByName} from '../../plugin'; import {sortPluginsByName} from '../../utils/pluginUtils';
import {PluginNotification} from '../../reducers/notifications'; import {PluginNotification} from '../../reducers/notifications';
import {ActiveSheet} from '../../reducers/application'; import {ActiveSheet} from '../../reducers/application';
import {State as Store} from '../../reducers'; import {State as Store} from '../../reducers';

View File

@@ -27,6 +27,7 @@ import {
} from 'flipper'; } from 'flipper';
import {StaticView} from '../../reducers/connections'; import {StaticView} from '../../reducers/connections';
import {BackgroundColorProperty} from 'csstype'; import {BackgroundColorProperty} from 'csstype';
import {getPluginTitle} from '../../utils/pluginUtils';
export type FlipperPlugins = typeof FlipperPlugin[]; export type FlipperPlugins = typeof FlipperPlugin[];
export type PluginsByCategory = [string, FlipperPlugins][]; export type PluginsByCategory = [string, FlipperPlugins][];
@@ -167,7 +168,7 @@ export const PluginSidebarListItem: React.FC<{
backgroundColor={starred === false ? colors.light20 : iconColor} backgroundColor={starred === false ? colors.light20 : iconColor}
color={colors.white} color={colors.white}
/> />
<PluginName>{plugin.title || plugin.id}</PluginName> <PluginName>{getPluginTitle(plugin)}</PluginName>
{starred !== undefined && (!starred || isActive) && ( {starred !== undefined && (!starred || isActive) && (
<ToggleButton <ToggleButton
onClick={onFavorite} onClick={onFavorite}

View File

@@ -9,7 +9,7 @@
import stream from 'stream'; import stream from 'stream';
import {FlipperDevicePlugin} from 'flipper'; import {FlipperDevicePlugin} from 'flipper';
import {sortPluginsByName} from '../plugin'; import {sortPluginsByName} from '../utils/pluginUtils';
export type LogLevel = export type LogLevel =
| 'unknown' | 'unknown'

View File

@@ -23,6 +23,7 @@ import {textContent} from '../utils/index';
import GK from '../fb-stubs/GK'; import GK from '../fb-stubs/GK';
import {deconstructPluginKey} from '../utils/clientUtils'; import {deconstructPluginKey} from '../utils/clientUtils';
import NotificationScreen from '../chrome/NotificationScreen'; import NotificationScreen from '../chrome/NotificationScreen';
import {getPluginTitle} from '../utils/pluginUtils';
type NotificationEvents = 'show' | 'click' | 'close' | 'reply' | 'action'; type NotificationEvents = 'show' | 'click' | 'close' | 'reply' | 'action';
const NOTIFICATION_THROTTLE = 5 * 1000; // in milliseconds const NOTIFICATION_THROTTLE = 5 * 1000; // in milliseconds
@@ -173,7 +174,9 @@ export default (store: Store, logger: Logger) => {
}, },
{ {
type: 'button', type: 'button',
text: `Hide all ${plugin != null ? plugin.title : ''}`, text: `Hide all ${
plugin != null ? getPluginTitle(plugin) : ''
}`,
}, },
], ],
closeButtonText: 'Hide', closeButtonText: 'Hide',

View File

@@ -19,7 +19,6 @@ import {serialize, deserialize} from './utils/serialization';
import {Idler} from './utils/Idler'; import {Idler} from './utils/Idler';
import {StaticView} from './reducers/connections'; import {StaticView} from './reducers/connections';
import {State as ReduxState} from './reducers'; import {State as ReduxState} from './reducers';
import {PersistedState} from './plugins/layout';
import {DEFAULT_MAX_QUEUE_SIZE} from './reducers/pluginMessageQueue'; import {DEFAULT_MAX_QUEUE_SIZE} from './reducers/pluginMessageQueue';
type Parameters = any; type Parameters = any;
@@ -275,10 +274,3 @@ export class FlipperPlugin<
this.init(); this.init();
} }
} }
export function sortPluginsByName(
a: typeof FlipperBasePlugin,
b: typeof FlipperBasePlugin,
): number {
return (a.title || a.id) > (b.title || b.id) ? 1 : -1;
}

View File

@@ -18,33 +18,45 @@ import type {State as PluginMessageQueueState} from '../../reducers/pluginStates
import {FlipperBasePlugin} from 'flipper'; import {FlipperBasePlugin} from 'flipper';
import type {ReduxState} from '../../reducers/index.tsx'; import type {ReduxState} from '../../reducers/index.tsx';
class MockFlipperPluginWithDefaultPersistedState extends FlipperBasePlugin< function createMockFlipperPluginWithDefaultPersistedState(id: string) {
return class MockFlipperPluginWithDefaultPersistedState extends FlipperBasePlugin<
*, *,
*, *,
{msg: string}, {msg: string},
> { > {
static id = id;
static defaultPersistedState = {msg: 'MockFlipperPluginWithPersistedState'}; static defaultPersistedState = {msg: 'MockFlipperPluginWithPersistedState'};
};
} }
class MockFlipperPluginWithExportPersistedState extends FlipperBasePlugin< function createMockFlipperPluginWithExportPersistedState(id: string) {
return class MockFlipperPluginWithExportPersistedState extends FlipperBasePlugin<
*, *,
*, *,
{msg: string}, {msg: string},
> { > {
static id = id;
static exportPersistedState = ( static exportPersistedState = (
callClient: (string, ?Object) => Promise<Object>, callClient: (string, ?Object) => Promise<Object>,
persistedState: ?{msg: string}, persistedState: ?{msg: string},
store: ?ReduxState, store: ?ReduxState,
): Promise<?{msg: string}> => { ): Promise<?{msg: string}> => {
return Promise.resolve({msg: 'MockFlipperPluginWithExportPersistedState'}); return Promise.resolve({
msg: 'MockFlipperPluginWithExportPersistedState',
});
};
}; };
} }
class MockFlipperPluginWithNoPersistedState extends FlipperBasePlugin< function createMockFlipperPluginWithNoPersistedState(id: string) {
return class MockFlipperPluginWithNoPersistedState extends FlipperBasePlugin<
*, *,
*, *,
*, *,
> {} > {
static id = id;
};
}
function mockPluginState( function mockPluginState(
gatekeepedPlugins: Array<PluginDefinition>, gatekeepedPlugins: Array<PluginDefinition>,
@@ -53,12 +65,24 @@ function mockPluginState(
): PluginsState { ): PluginsState {
return { return {
devicePlugins: new Map([ devicePlugins: new Map([
['DevicePlugin1', MockFlipperPluginWithDefaultPersistedState], [
['DevicePlugin2', MockFlipperPluginWithDefaultPersistedState], 'DevicePlugin1',
createMockFlipperPluginWithDefaultPersistedState('DevicePlugin1'),
],
[
'DevicePlugin2',
createMockFlipperPluginWithDefaultPersistedState('DevicePlugin2'),
],
]), ]),
clientPlugins: new Map([ clientPlugins: new Map([
['ClientPlugin1', MockFlipperPluginWithDefaultPersistedState], [
['ClientPlugin2', MockFlipperPluginWithDefaultPersistedState], 'ClientPlugin1',
createMockFlipperPluginWithDefaultPersistedState('ClientPlugin1'),
],
[
'ClientPlugin2',
createMockFlipperPluginWithDefaultPersistedState('ClientPlugin2'),
],
]), ]),
gatekeepedPlugins, gatekeepedPlugins,
disabledPlugins, disabledPlugins,
@@ -98,12 +122,24 @@ test('getPersistentPlugins with no plugins getting excluded', () => {
test('getPersistentPlugins, where the plugins with exportPersistedState not getting excluded', () => { test('getPersistentPlugins, where the plugins with exportPersistedState not getting excluded', () => {
const state: PluginsState = { const state: PluginsState = {
devicePlugins: new Map([ devicePlugins: new Map([
['DevicePlugin1', MockFlipperPluginWithExportPersistedState], [
['DevicePlugin2', MockFlipperPluginWithExportPersistedState], 'DevicePlugin1',
createMockFlipperPluginWithExportPersistedState('DevicePlugin1'),
],
[
'DevicePlugin2',
createMockFlipperPluginWithExportPersistedState('DevicePlugin2'),
],
]), ]),
clientPlugins: new Map([ clientPlugins: new Map([
['ClientPlugin1', MockFlipperPluginWithExportPersistedState], [
['ClientPlugin2', MockFlipperPluginWithExportPersistedState], 'ClientPlugin1',
createMockFlipperPluginWithExportPersistedState('ClientPlugin1'),
],
[
'ClientPlugin2',
createMockFlipperPluginWithExportPersistedState('ClientPlugin2'),
],
]), ]),
gatekeepedPlugins: [], gatekeepedPlugins: [],
disabledPlugins: [], disabledPlugins: [],
@@ -122,12 +158,24 @@ test('getPersistentPlugins, where the plugins with exportPersistedState not gett
test('getPersistentPlugins, where the non persistent plugins getting excluded', () => { test('getPersistentPlugins, where the non persistent plugins getting excluded', () => {
const state: PluginsState = { const state: PluginsState = {
devicePlugins: new Map([ devicePlugins: new Map([
['DevicePlugin1', MockFlipperPluginWithNoPersistedState], [
['DevicePlugin2', MockFlipperPluginWithDefaultPersistedState], 'DevicePlugin1',
createMockFlipperPluginWithNoPersistedState('DevicePlugin1'),
],
[
'DevicePlugin2',
createMockFlipperPluginWithDefaultPersistedState('DevicePlugin2'),
],
]), ]),
clientPlugins: new Map([ clientPlugins: new Map([
['ClientPlugin1', MockFlipperPluginWithDefaultPersistedState], [
['ClientPlugin2', MockFlipperPluginWithNoPersistedState], 'ClientPlugin1',
createMockFlipperPluginWithDefaultPersistedState('ClientPlugin1'),
],
[
'ClientPlugin2',
createMockFlipperPluginWithNoPersistedState('ClientPlugin2'),
],
]), ]),
gatekeepedPlugins: [], gatekeepedPlugins: [],
disabledPlugins: [], disabledPlugins: [],
@@ -141,12 +189,24 @@ test('getPersistentPlugins, where the non persistent plugins getting excluded',
test('getActivePersistentPlugins, where the non persistent plugins getting excluded', () => { test('getActivePersistentPlugins, where the non persistent plugins getting excluded', () => {
const state: PluginsState = { const state: PluginsState = {
devicePlugins: new Map([ devicePlugins: new Map([
['DevicePlugin1', MockFlipperPluginWithNoPersistedState], [
['DevicePlugin2', MockFlipperPluginWithDefaultPersistedState], 'DevicePlugin1',
createMockFlipperPluginWithNoPersistedState('DevicePlugin1'),
],
[
'DevicePlugin2',
createMockFlipperPluginWithDefaultPersistedState('DevicePlugin2'),
],
]), ]),
clientPlugins: new Map([ clientPlugins: new Map([
['ClientPlugin1', MockFlipperPluginWithDefaultPersistedState], [
['ClientPlugin2', MockFlipperPluginWithNoPersistedState], 'ClientPlugin1',
createMockFlipperPluginWithDefaultPersistedState('ClientPlugin1'),
],
[
'ClientPlugin2',
createMockFlipperPluginWithNoPersistedState('ClientPlugin2'),
],
]), ]),
gatekeepedPlugins: [], gatekeepedPlugins: [],
disabledPlugins: [], disabledPlugins: [],
@@ -161,19 +221,43 @@ test('getActivePersistentPlugins, where the non persistent plugins getting exclu
}; };
const queues: PluginMessageQueueState = {}; const queues: PluginMessageQueueState = {};
const list = getActivePersistentPlugins(plugins, queues, state); 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', () => { test('getActivePersistentPlugins, where the plugins not in pluginState or queue gets excluded', () => {
const state: PluginsState = { const state: PluginsState = {
devicePlugins: new Map([ devicePlugins: new Map([
['DevicePlugin1', MockFlipperPluginWithDefaultPersistedState], [
['DevicePlugin2', MockFlipperPluginWithDefaultPersistedState], 'DevicePlugin1',
createMockFlipperPluginWithDefaultPersistedState('DevicePlugin1'),
],
[
'DevicePlugin2',
createMockFlipperPluginWithDefaultPersistedState('DevicePlugin2'),
],
]), ]),
clientPlugins: new Map([ clientPlugins: new Map([
['ClientPlugin1', MockFlipperPluginWithDefaultPersistedState], [
['ClientPlugin2', MockFlipperPluginWithDefaultPersistedState], 'ClientPlugin1',
['ClientPlugin3', MockFlipperPluginWithDefaultPersistedState], createMockFlipperPluginWithDefaultPersistedState('ClientPlugin1'),
],
[
'ClientPlugin2',
createMockFlipperPluginWithDefaultPersistedState('ClientPlugin2'),
],
[
'ClientPlugin3',
createMockFlipperPluginWithDefaultPersistedState('ClientPlugin3'),
],
]), ]),
gatekeepedPlugins: [], gatekeepedPlugins: [],
disabledPlugins: [], disabledPlugins: [],
@@ -190,5 +274,18 @@ test('getActivePersistentPlugins, where the plugins not in pluginState or queue
], ],
}; };
const list = getActivePersistentPlugins(plugins, queues, state); 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',
},
]);
}); });

View File

@@ -42,6 +42,7 @@ import {setSelectPluginsToExportActiveSheet} from '../reducers/application';
import {deconstructClientId, deconstructPluginKey} from '../utils/clientUtils'; import {deconstructClientId, deconstructPluginKey} from '../utils/clientUtils';
import {performance} from 'perf_hooks'; import {performance} from 'perf_hooks';
import {processMessageQueue} from './messageQueue'; import {processMessageQueue} from './messageQueue';
import {getPluginTitle} from './pluginUtils';
export const IMPORT_FLIPPER_TRACE_EVENT = 'import-flipper-trace'; export const IMPORT_FLIPPER_TRACE_EVENT = 'import-flipper-trace';
export const EXPORT_FLIPPER_TRACE_EVENT = 'export-flipper-trace'; export const EXPORT_FLIPPER_TRACE_EVENT = 'export-flipper-trace';
@@ -85,7 +86,8 @@ type SerializePluginStatesOptions = {
type PluginsToProcess = { type PluginsToProcess = {
pluginKey: string; pluginKey: string;
plugin: string; pluginId: string;
pluginName: string;
pluginClass: typeof FlipperPlugin | typeof FlipperDevicePlugin; pluginClass: typeof FlipperPlugin | typeof FlipperDevicePlugin;
client: Client; client: Client;
}[]; }[];
@@ -398,33 +400,39 @@ export async function fetchMetadata(
const newPluginState = {...pluginStates}; const newPluginState = {...pluginStates};
const errorArray: Array<Error> = []; 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; const exportState = pluginClass ? pluginClass.exportPersistedState : null;
if (exportState) { if (exportState) {
const fetchMetaDataMarker = `${EXPORT_FLIPPER_TRACE_EVENT}:fetch-meta-data-per-plugin`; const fetchMetaDataMarker = `${EXPORT_FLIPPER_TRACE_EVENT}:fetch-meta-data-per-plugin`;
performance.mark(fetchMetaDataMarker); performance.mark(fetchMetaDataMarker);
try { try {
statusUpdate && statusUpdate &&
statusUpdate(`Fetching metadata for plugin ${plugin}...`); statusUpdate(`Fetching metadata for plugin ${pluginName}...`);
const data = await promiseTimeout( const data = await promiseTimeout(
240000, // Fetching MobileConfig data takes ~ 3 mins, thus keeping timeout at 4 mins. 240000, // Fetching MobileConfig data takes ~ 3 mins, thus keeping timeout at 4 mins.
exportState( exportState(
callClient(client, plugin), callClient(client, pluginId),
newPluginState[pluginKey], newPluginState[pluginKey],
state, state,
idler, idler,
statusUpdate, statusUpdate,
), ),
`Timed out while collecting data for ${plugin}`, `Timed out while collecting data for ${pluginName}`,
); );
getLogger().trackTimeSince(fetchMetaDataMarker, fetchMetaDataMarker, { getLogger().trackTimeSince(fetchMetaDataMarker, fetchMetaDataMarker, {
plugin, pluginId,
}); });
newPluginState[pluginKey] = data; newPluginState[pluginKey] = data;
} catch (e) { } catch (e) {
errorArray.push(e); errorArray.push(e);
getLogger().trackTimeSince(fetchMetaDataMarker, fetchMetaDataMarker, { getLogger().trackTimeSince(fetchMetaDataMarker, fetchMetaDataMarker, {
plugin, pluginId,
error: e, error: e,
}); });
continue; continue;
@@ -441,7 +449,12 @@ async function processQueues(
statusUpdate?: (msg: string) => void, statusUpdate?: (msg: string) => void,
idler?: Idler, idler?: Idler,
) { ) {
for (const {plugin, pluginKey, pluginClass} of pluginsToProcess) { for (const {
pluginName,
pluginId,
pluginKey,
pluginClass,
} of pluginsToProcess) {
if (pluginClass.persistedStateReducer) { if (pluginClass.persistedStateReducer) {
const processQueueMarker = `${EXPORT_FLIPPER_TRACE_EVENT}:process-queue-per-plugin`; const processQueueMarker = `${EXPORT_FLIPPER_TRACE_EVENT}:process-queue-per-plugin`;
performance.mark(processQueueMarker); performance.mark(processQueueMarker);
@@ -454,14 +467,14 @@ async function processQueues(
statusUpdate?.( statusUpdate?.(
`Processing event ${current} / ${total} (${Math.round( `Processing event ${current} / ${total} (${Math.round(
(current / total) * 100, (current / total) * 100,
)}%) for plugin ${plugin}`, )}%) for plugin ${pluginName}`,
); );
}, },
idler, idler,
); );
getLogger().trackTimeSince(processQueueMarker, processQueueMarker, { getLogger().trackTimeSince(processQueueMarker, processQueueMarker, {
plugin, pluginId,
}); });
} }
} }
@@ -506,7 +519,8 @@ export function determinePluginsToProcess(
pluginsToProcess.push({ pluginsToProcess.push({
pluginKey: key, pluginKey: key,
client, client,
plugin, pluginId: plugin,
pluginName: getPluginTitle(pluginClass),
pluginClass, pluginClass,
}); });
} }

View File

@@ -77,13 +77,15 @@ export function getActivePersistentPlugins(
pluginsMessageQueue: PluginMessageQueueState, pluginsMessageQueue: PluginMessageQueueState,
plugins: PluginsState, plugins: PluginsState,
selectedClient?: Client, selectedClient?: Client,
): Array<string> { ): {id: string; label: string}[] {
const pluginsMap: Map< const pluginsMap: Map<
string, string,
typeof FlipperDevicePlugin | typeof FlipperPlugin typeof FlipperDevicePlugin | typeof FlipperPlugin
> = pluginsClassMap(plugins); > = pluginsClassMap(plugins);
return getPersistentPlugins(plugins).filter(plugin => { return getPersistentPlugins(plugins)
const pluginClass = pluginsMap.get(plugin); .map(pluginName => pluginsMap.get(pluginName)!)
.sort(sortPluginsByName)
.map(plugin => {
const keys = [ const keys = [
...new Set([ ...new Set([
...Object.keys(pluginsState), ...Object.keys(pluginsState),
@@ -92,23 +94,29 @@ export function getActivePersistentPlugins(
] ]
.filter(k => !selectedClient || k.includes(selectedClient.id)) .filter(k => !selectedClient || k.includes(selectedClient.id))
.map(key => deconstructPluginKey(key).pluginName); .map(key => deconstructPluginKey(key).pluginName);
let result = plugin == 'DeviceLogs'; let result = plugin.id == 'DeviceLogs';
const pluginsWithExportPersistedState = const pluginsWithExportPersistedState =
pluginClass && pluginClass.exportPersistedState != undefined; plugin && plugin.exportPersistedState != undefined;
const pluginsWithReduxData = keys.includes(plugin); const pluginsWithReduxData = keys.includes(plugin.id);
if (!result && selectedClient) { if (!result && selectedClient) {
// If there is a selected client, active persistent plugin is the plugin which is active for selectedClient and also persistent. // If there is a selected client, active persistent plugin is the plugin which is active for selectedClient and also persistent.
result = result =
selectedClient.plugins.includes(plugin) && selectedClient.plugins.includes(plugin.id) &&
(pluginsWithExportPersistedState || pluginsWithReduxData); (pluginsWithExportPersistedState || pluginsWithReduxData);
} else if (!result && !selectedClient) { } else if (!result && !selectedClient) {
// If there is no selected client, active persistent plugin is the plugin which is just persistent. // If there is no selected client, active persistent plugin is the plugin which is just persistent.
result = result =
(pluginClass && pluginClass.exportPersistedState != undefined) || (plugin && plugin.exportPersistedState != undefined) ||
keys.includes(plugin); keys.includes(plugin.id);
} }
return result; return (result
}); ? {
id: plugin.id,
label: getPluginTitle(plugin),
}
: undefined)!;
})
.filter(Boolean);
} }
export function getPersistentPlugins(plugins: PluginsState): Array<string> { 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;
}