From f9fa80d93bdba7ac5ccf0550b644d6235a4cbf81 Mon Sep 17 00:00:00 2001 From: Chaiwat Ekkaewnumchai Date: Fri, 23 Aug 2019 04:40:41 -0700 Subject: [PATCH] Expand/Collapse Plugin Sidebar v1 Summary: * Change the way to determine recently used plugins * Show all plugins if there are just a few hidden plugins * Not all of plugins in client list can be showed, so checking happens when rendering * Add action to clear the history internally (for testing) (not sure if needed) Reviewed By: danielbuechele Differential Revision: D16965302 fbshipit-source-id: 6efeedac8c0fad7e89a96e7fc5ba9101d3516fe7 --- src/Client.tsx | 32 +++++++++---- src/chrome/MainSidebar.tsx | 93 ++++++++++++++++++++++-------------- src/reducers/connections.tsx | 37 +++++++------- 3 files changed, 101 insertions(+), 61 deletions(-) diff --git a/src/Client.tsx b/src/Client.tsx index 1d6c76fd5..586d00d37 100644 --- a/src/Client.tsx +++ b/src/Client.tsx @@ -92,6 +92,11 @@ const handleError = ( } }; +export const MAX_MINIMUM_PLUGINS = 5; +export const SHOW_REMAINING_PLUGIN_IF_LESS_THAN = 3; +export const SAVED_PLUGINS_COUNT = + MAX_MINIMUM_PLUGINS + SHOW_REMAINING_PLUGIN_IF_LESS_THAN; + export default class Client extends EventEmitter { app: App; connected: boolean; @@ -176,15 +181,24 @@ export default class Client extends EventEmitter { } /// Sort plugins by LRU order stored in lessPlugins; if not, sort by alphabet - byClientLRU(a: typeof FlipperPlugin, b: typeof FlipperPlugin): number { - const hasA = this.lessPlugins.includes(a.id); - const hasB = this.lessPlugins.includes(b.id); - if (hasA && hasB) { - return this.lessPlugins.indexOf(a.id) > this.lessPlugins.indexOf(b.id) - ? 1 - : -1; - } else if (hasA !== hasB) { - return hasB ? 1 : -1; + byClientLRU( + pluginsCount: number, + a: typeof FlipperPlugin, + b: typeof FlipperPlugin, + ): number { + // Sanity check + if (this.lessPlugins !== null) { + const showPluginsCount = + pluginsCount >= MAX_MINIMUM_PLUGINS + SHOW_REMAINING_PLUGIN_IF_LESS_THAN + ? MAX_MINIMUM_PLUGINS + : pluginsCount; + let idxA = this.lessPlugins.indexOf(a.id); + idxA = idxA < 0 || idxA >= showPluginsCount ? showPluginsCount : idxA; + let idxB = this.lessPlugins.indexOf(b.id); + idxB = idxB < 0 || idxB >= showPluginsCount ? showPluginsCount : idxB; + if (idxA !== idxB) { + return idxA > idxB ? 1 : -1; + } } return (a.title || a.id) > (b.title || b.id) ? 1 : -1; } diff --git a/src/chrome/MainSidebar.tsx b/src/chrome/MainSidebar.tsx index 19af229ce..b02e02a76 100644 --- a/src/chrome/MainSidebar.tsx +++ b/src/chrome/MainSidebar.tsx @@ -35,6 +35,10 @@ import {setActiveSheet} from '../reducers/application'; import UserAccount from './UserAccount'; import {connect} from 'react-redux'; import {BackgroundColorProperty} from 'csstype'; +import { + MAX_MINIMUM_PLUGINS, + SHOW_REMAINING_PLUGIN_IF_LESS_THAN, +} from '../Client'; const ListItem = styled('div')(({active}: {active?: boolean}) => ({ paddingLeft: 10, @@ -316,42 +320,61 @@ class MainSidebar extends PureComponent { // Display their plugins under all selected devices until they die out client.query.device_id === 'unknown', ) - .map((client: Client) => ( - - {client.query.app} - {Array.from(this.props.clientPlugins.values()) - .filter( - p => - (client.showAllPlugins - ? client.plugins - : client.lessPlugins - ).indexOf(p.id) > -1, - ) - .sort((a, b) => client.byClientLRU(a, b)) - .map(plugin => ( - { + const plugins = Array.from( + this.props.clientPlugins.values(), + ).filter( + (p: typeof FlipperPlugin) => client.plugins.indexOf(p.id) > -1, + ); + + const minShowPluginsCount = + plugins.length < + MAX_MINIMUM_PLUGINS + SHOW_REMAINING_PLUGIN_IF_LESS_THAN + ? plugins.length + : MAX_MINIMUM_PLUGINS; + + return ( + + {client.query.app} + {plugins + .sort((a: typeof FlipperPlugin, b: typeof FlipperPlugin) => + client.byClientLRU(plugins.length, a, b), + ) + .slice( + 0, + client.showAllPlugins + ? client.plugins.length + : minShowPluginsCount, + ) + .map((plugin: typeof FlipperPlugin) => ( + + selectPlugin({ + selectedPlugin: plugin.id, + selectedApp: client.id, + deepLinkPayload: null, + }) + } + plugin={plugin} + app={client.query.app} + /> + ))} + {plugins.length > minShowPluginsCount && ( + - selectPlugin({ - selectedPlugin: plugin.id, - selectedApp: client.id, - deepLinkPayload: null, - }) - } - plugin={plugin} - app={client.query.app} - /> - ))} - this.props.showMoreOrLessPlugins(client.id)}> - {client.showAllPlugins ? 'Show less' : 'Show more'} - - - ))} + this.props.showMoreOrLessPlugins(client.id) + }> + {client.showAllPlugins ? 'Show less' : 'Show more'} + + )} + + ); + })} {uninitializedClients.map(entry => ( {entry.client.appName} diff --git a/src/reducers/connections.tsx b/src/reducers/connections.tsx index c5062e313..65527db3d 100644 --- a/src/reducers/connections.tsx +++ b/src/reducers/connections.tsx @@ -12,6 +12,7 @@ import {UninitializedClient} from '../UninitializedClient'; import {isEqual} from 'lodash'; import iosUtil from '../fb-stubs/iOSContainerUtility'; import {performance} from 'perf_hooks'; +import {SAVED_PLUGINS_COUNT} from '../Client'; export type State = { devices: Array; @@ -33,8 +34,6 @@ export type State = { deepLinkPayload: null | string; }; -const MAX_MINIMUM_PLUGINS = 5; - export type Action = | { type: 'UNREGISTER_DEVICES'; @@ -99,7 +98,8 @@ export type Action = | { type: 'CLIENT_SHOW_MORE_OR_LESS'; payload: string; - }; + } + | {type: 'CLEAR_LRU_PLUGINS_HISTORY'}; const DEFAULT_PLUGIN = 'DeviceLogs'; const DEFAULT_DEVICE_BLACKLIST = [MacDevice]; @@ -215,20 +215,19 @@ const reducer = (state: State = INITAL_STATE, action: Action): State => { performance.mark(`activePlugin-${selectedPlugin}`); } - const LRUPlugins = ( - state.userLRUPlugins[selectedApp || state.userPreferredApp] || [] - ).slice(); + const userPreferredApp = selectedApp || state.userPreferredApp; + const LRUPlugins = (state.userLRUPlugins[userPreferredApp] || []).slice(); const idxLRU = LRUPlugins.indexOf(selectedPlugin); if (idxLRU >= 0) { LRUPlugins.splice(idxLRU, 1); } LRUPlugins.unshift(selectedPlugin); - LRUPlugins.splice(MAX_MINIMUM_PLUGINS); + LRUPlugins.splice(SAVED_PLUGINS_COUNT); return { ...state, ...payload, - userPreferredApp: selectedApp || state.userPreferredApp, + userPreferredApp: userPreferredApp, userPreferredPlugin: selectedPlugin, userLRUPlugins: {...state.userLRUPlugins, [selectedApp]: LRUPlugins}, }; @@ -242,15 +241,7 @@ const reducer = (state: State = INITAL_STATE, action: Action): State => { const {userPreferredApp, userPreferredPlugin, userLRUPlugins} = state; let {selectedApp, selectedPlugin} = state; - const lessPlugins = (userLRUPlugins[payload.id] || []).slice(); - if (lessPlugins) { - payload.lessPlugins = lessPlugins.concat( - payload.plugins.filter(p => !lessPlugins.includes(p)), - ); - } else { - payload.lessPlugins = payload.plugins.slice(); - } - payload.lessPlugins = payload.lessPlugins.slice(0, MAX_MINIMUM_PLUGINS); + payload.lessPlugins = (userLRUPlugins[payload.id] || []).slice(); if ( userPreferredApp && @@ -383,6 +374,18 @@ const reducer = (state: State = INITAL_STATE, action: Action): State => { }), }; } + case 'CLEAR_LRU_PLUGINS_HISTORY': { + const clearLRUPlugins: Map> = new Map(); + state.userLRUPlugins.forEach((_, key) => { + if (key !== null) { + clearLRUPlugins.set(key, []); + } + }); + return { + ...state, + userLRUPlugins: clearLRUPlugins, + }; + } default: return state; }