Introduce support for categorizing plugins
Summary: This PR introduces the possibility to group plugins in categories. The category can be determined by setting the `category` field in `package.json`. Categories are sorted alphabetically. Categories are shown below all uncategorized items. Within categories, items are sorted as before: by last recently usage. Design wise, the category name might now look more prominent than the app name, this is to be addressed in a follow up PR. Reviewed By: jknoxville Differential Revision: D18169459 fbshipit-source-id: 77deb0f27a0462a0d449944ddc262396160687a2
This commit is contained in:
committed by
Facebook Github Bot
parent
b073c90e24
commit
494ffd26b3
@@ -52,6 +52,7 @@ you can also specify a title to show in the Flipper sidebar and an icon to displ
|
|||||||
"keywords": ["flipper-plugin"],
|
"keywords": ["flipper-plugin"],
|
||||||
"icon": "apps",
|
"icon": "apps",
|
||||||
"title": "Sea Mammals",
|
"title": "Sea Mammals",
|
||||||
|
"category": "Example Plugin",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"flipper": "latest"
|
"flipper": "latest"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -118,6 +118,12 @@ const PluginName = styled(Text)(
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const CategoryName = styled(PluginName)({
|
||||||
|
color: colors.macOSSidebarSectionTitle,
|
||||||
|
textTransform: 'uppercase',
|
||||||
|
fontSize: '0.9em',
|
||||||
|
});
|
||||||
|
|
||||||
const Plugins = styled(FlexColumn)({
|
const Plugins = styled(FlexColumn)({
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
overflow: 'auto',
|
overflow: 'auto',
|
||||||
@@ -386,34 +392,45 @@ class MainSidebar extends PureComponent<Props, State> {
|
|||||||
return (
|
return (
|
||||||
<React.Fragment key={client.id}>
|
<React.Fragment key={client.id}>
|
||||||
<SidebarHeader>{client.query.app}</SidebarHeader>
|
<SidebarHeader>{client.query.app}</SidebarHeader>
|
||||||
{plugins
|
{groupPluginsByCategory(
|
||||||
.sort((a: typeof FlipperPlugin, b: typeof FlipperPlugin) =>
|
plugins
|
||||||
client.byClientLRU(plugins.length, a, b),
|
.sort(
|
||||||
)
|
(a: typeof FlipperPlugin, b: typeof FlipperPlugin) =>
|
||||||
.slice(
|
client.byClientLRU(plugins.length, a, b),
|
||||||
0,
|
)
|
||||||
client.showAllPlugins
|
.slice(
|
||||||
? client.plugins.length
|
0,
|
||||||
: minShowPluginsCount,
|
client.showAllPlugins
|
||||||
)
|
? client.plugins.length
|
||||||
.map((plugin: typeof FlipperPlugin) => (
|
: minShowPluginsCount,
|
||||||
<PluginSidebarListItem
|
),
|
||||||
key={plugin.id}
|
).map(([category, plugins]) => (
|
||||||
isActive={
|
<>
|
||||||
plugin.id === selectedPlugin &&
|
{category && (
|
||||||
selectedApp === client.id
|
<ListItem>
|
||||||
}
|
<CategoryName>{category}</CategoryName>
|
||||||
onClick={() =>
|
</ListItem>
|
||||||
selectPlugin({
|
)}
|
||||||
selectedPlugin: plugin.id,
|
{plugins.map(plugin => (
|
||||||
selectedApp: client.id,
|
<PluginSidebarListItem
|
||||||
deepLinkPayload: null,
|
key={plugin.id}
|
||||||
})
|
isActive={
|
||||||
}
|
plugin.id === selectedPlugin &&
|
||||||
plugin={plugin}
|
selectedApp === client.id
|
||||||
app={client.query.app}
|
}
|
||||||
/>
|
onClick={() =>
|
||||||
))}
|
selectPlugin({
|
||||||
|
selectedPlugin: plugin.id,
|
||||||
|
selectedApp: client.id,
|
||||||
|
deepLinkPayload: null,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
plugin={plugin}
|
||||||
|
app={client.query.app}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
))}
|
||||||
{plugins.length > minShowPluginsCount && (
|
{plugins.length > minShowPluginsCount && (
|
||||||
<PluginShowMoreOrLess
|
<PluginShowMoreOrLess
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
@@ -452,6 +469,27 @@ class MainSidebar extends PureComponent<Props, State> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PluginsByCategory = [string, (typeof FlipperPlugin)[]][];
|
||||||
|
|
||||||
|
function groupPluginsByCategory(
|
||||||
|
plugins: (typeof FlipperPlugin)[],
|
||||||
|
): PluginsByCategory {
|
||||||
|
// Pre condition: plugins are already sorted globally
|
||||||
|
const byCategory: {[cat: string]: (typeof FlipperPlugin)[]} = {};
|
||||||
|
const res: PluginsByCategory = [];
|
||||||
|
plugins.forEach(plugin => {
|
||||||
|
const category = plugin.category || '';
|
||||||
|
(byCategory[category] || (byCategory[category] = [])).push(plugin);
|
||||||
|
});
|
||||||
|
// Sort categories
|
||||||
|
Object.keys(byCategory)
|
||||||
|
.sort()
|
||||||
|
.forEach(category => {
|
||||||
|
res.push([category, byCategory[category]]);
|
||||||
|
});
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
export default connect<StateFromProps, DispatchFromProps, OwnProps, Store>(
|
export default connect<StateFromProps, DispatchFromProps, OwnProps, Store>(
|
||||||
({
|
({
|
||||||
application: {windowIsFocused},
|
application: {windowIsFocused},
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ export abstract class FlipperBasePlugin<
|
|||||||
> extends Component<Props<PersistedState>, State> {
|
> extends Component<Props<PersistedState>, State> {
|
||||||
abstract ['constructor']: any;
|
abstract ['constructor']: any;
|
||||||
static title: string | null = null;
|
static title: string | null = null;
|
||||||
|
static category: string | null = null;
|
||||||
static id: string = '';
|
static id: string = '';
|
||||||
static icon: string | null = null;
|
static icon: string | null = null;
|
||||||
static gatekeeper: string | null = null;
|
static gatekeeper: string | null = null;
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "sea-mammals",
|
"name": "sea-mammals",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"main": "index.tsx",
|
"main": "index.tsx",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"keywords": ["flipper-plugin"],
|
"keywords": ["flipper-plugin"],
|
||||||
"icon": "apps",
|
"icon": "apps",
|
||||||
"title": "Sea Mammals",
|
"title": "Sea Mammals",
|
||||||
"bugs": {
|
"category": "Example Plugin",
|
||||||
"email": "realpassy@fb.com"
|
"bugs": {
|
||||||
}
|
"email": "realpassy@fb.com"
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user