From 2ca52f81d2fac34392545d89d1af4d9abe7e52df Mon Sep 17 00:00:00 2001 From: Michel Weststrate Date: Tue, 16 Mar 2021 14:54:53 -0700 Subject: [PATCH] Introduce pluginKey Summary: Exposed the `pluginKey` to sandy plugins (which we will use later for storing table preferences per plugin). And a little moving code around because circular deps problem roared its ugly head again. Reviewed By: nikoant Differential Revision: D27009721 fbshipit-source-id: 7ad29e72ff8028c9daae270c4749b657bd8ff049 --- desktop/app/src/Client.tsx | 16 +++++++++------- desktop/app/src/PluginContainer.tsx | 3 +-- desktop/app/src/devices/BaseDevice.tsx | 6 ++++++ desktop/app/src/dispatcher/notifications.tsx | 4 ++-- desktop/app/src/plugin.tsx | 6 ------ desktop/app/src/utils/exportData.tsx | 3 +-- desktop/app/src/utils/messageQueue.tsx | 2 +- desktop/app/src/utils/onRegisterDevice.tsx | 9 ++++----- desktop/app/src/utils/pluginUtils.tsx | 7 ++++++- .../flipper-plugin/src/plugin/DevicePlugin.tsx | 3 ++- desktop/flipper-plugin/src/plugin/Plugin.tsx | 9 ++++++++- desktop/flipper-plugin/src/plugin/PluginBase.tsx | 7 +++++++ .../flipper-plugin/src/plugin/PluginContext.tsx | 15 +++++++++++---- .../flipper-plugin/src/test-utils/test-utils.tsx | 2 ++ .../src/ui/datatable/DataTable.tsx | 4 ++-- .../src/ui/datatable/DataTableManager.tsx | 3 +-- 16 files changed, 63 insertions(+), 36 deletions(-) diff --git a/desktop/app/src/Client.tsx b/desktop/app/src/Client.tsx index 2b5e06a8a9d..93ef7cb8d81 100644 --- a/desktop/app/src/Client.tsx +++ b/desktop/app/src/Client.tsx @@ -7,12 +7,7 @@ * @format */ -import { - PluginDefinition, - isSandyPlugin, - FlipperPlugin, - FlipperDevicePlugin, -} from './plugin'; +import {PluginDefinition, FlipperPlugin, FlipperDevicePlugin} from './plugin'; import BaseDevice, {OS} from './devices/BaseDevice'; import {Logger} from './fb-interfaces/Logger'; import {Store} from './reducers/index'; @@ -30,6 +25,7 @@ import invariant from 'invariant'; import { getPluginKey, defaultEnabledBackgroundPlugins, + isSandyPlugin, } from './utils/pluginUtils'; import {processMessagesLater} from './utils/messageQueue'; import {emitBytesReceived} from './dispatcher/tracking'; @@ -260,6 +256,7 @@ export default class Client extends EventEmitter { _getFlipperLibImplementation(), plugin, this, + getPluginKey(this.id, {serial: this.query.device_id}, plugin.id), initialStates[pluginId], ), ); @@ -306,7 +303,12 @@ export default class Client extends EventEmitter { // TODO: needs to be wrapped in error tracking T68955280 this.sandyPluginStates.set( plugin.id, - new _SandyPluginInstance(_getFlipperLibImplementation(), plugin, this), + new _SandyPluginInstance( + _getFlipperLibImplementation(), + plugin, + this, + getPluginKey(this.id, {serial: this.query.device_id}, plugin.id), + ), ); } } diff --git a/desktop/app/src/PluginContainer.tsx b/desktop/app/src/PluginContainer.tsx index 09b91993cbe..a35c13f93b1 100644 --- a/desktop/app/src/PluginContainer.tsx +++ b/desktop/app/src/PluginContainer.tsx @@ -12,7 +12,6 @@ import { FlipperDevicePlugin, Props as PluginProps, PluginDefinition, - isSandyPlugin, } from './plugin'; import {Logger} from './fb-interfaces/Logger'; import BaseDevice from './devices/BaseDevice'; @@ -47,7 +46,7 @@ import {IdlerImpl} from './utils/Idler'; import {processMessageQueue} from './utils/messageQueue'; import {ToggleButton, SmallText, Layout} from './ui'; import {theme, TrackingScope, _SandyPluginRenderer} from 'flipper-plugin'; -import {isDevicePluginDefinition} from './utils/pluginUtils'; +import {isDevicePluginDefinition, isSandyPlugin} from './utils/pluginUtils'; import {ContentContainer} from './sandy-chrome/ContentContainer'; import {Alert, Typography} from 'antd'; import {InstalledPluginDetails} from 'plugin-lib'; diff --git a/desktop/app/src/devices/BaseDevice.tsx b/desktop/app/src/devices/BaseDevice.tsx index 27bb89cadf3..c601d829671 100644 --- a/desktop/app/src/devices/BaseDevice.tsx +++ b/desktop/app/src/devices/BaseDevice.tsx @@ -242,6 +242,12 @@ export default class BaseDevice { _getFlipperLibImplementation(), plugin, this, + // break circular dep, one of those days again... + require('../utils/pluginUtils').getPluginKey( + undefined, + {serial: this.serial}, + plugin.id, + ), initialState, ), ); diff --git a/desktop/app/src/dispatcher/notifications.tsx b/desktop/app/src/dispatcher/notifications.tsx index f086d98332d..a536b225373 100644 --- a/desktop/app/src/dispatcher/notifications.tsx +++ b/desktop/app/src/dispatcher/notifications.tsx @@ -10,7 +10,7 @@ import {Store} from '../reducers/index'; import {Logger} from '../fb-interfaces/Logger'; import {PluginNotification} from '../reducers/notifications'; -import {PluginDefinition, isSandyPlugin} from '../plugin'; +import {PluginDefinition} from '../plugin'; import {setStaticView} from '../reducers/connections'; import {ipcRenderer, IpcRendererEvent} from 'electron'; import { @@ -22,7 +22,7 @@ import {textContent} from '../utils/index'; import GK from '../fb-stubs/GK'; import {deconstructPluginKey} from '../utils/clientUtils'; import NotificationScreen from '../chrome/NotificationScreen'; -import {getPluginTitle} from '../utils/pluginUtils'; +import {getPluginTitle, isSandyPlugin} from '../utils/pluginUtils'; import {sideEffect} from '../utils/sideEffect'; type NotificationEvents = 'show' | 'click' | 'close' | 'reply' | 'action'; diff --git a/desktop/app/src/plugin.tsx b/desktop/app/src/plugin.tsx index b1f63387b4f..9ee77c33c74 100644 --- a/desktop/app/src/plugin.tsx +++ b/desktop/app/src/plugin.tsx @@ -36,12 +36,6 @@ export type ClientPluginDefinition = export type ClientPluginMap = Map; export type DevicePluginMap = Map; -export function isSandyPlugin( - plugin?: PluginDefinition | null, -): plugin is _SandyPluginDefinition { - return plugin instanceof _SandyPluginDefinition; -} - // This function is intended to be called from outside of the plugin. // If you want to `call` from the plugin use, this.client.call export function callClient( diff --git a/desktop/app/src/utils/exportData.tsx b/desktop/app/src/utils/exportData.tsx index a4193662921..9cbac571896 100644 --- a/desktop/app/src/utils/exportData.tsx +++ b/desktop/app/src/utils/exportData.tsx @@ -25,7 +25,6 @@ import { PluginDefinition, DevicePluginMap, ClientPluginMap, - isSandyPlugin, } from '../plugin'; import {default as BaseDevice} from '../devices/BaseDevice'; import {default as ArchivedDevice} from '../devices/ArchivedDevice'; @@ -46,7 +45,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'; +import {getPluginTitle, isSandyPlugin} from './pluginUtils'; import {capture} from './screenshot'; import {uploadFlipperMedia} from '../fb-stubs/user'; import {Idler} from 'flipper-plugin'; diff --git a/desktop/app/src/utils/messageQueue.tsx b/desktop/app/src/utils/messageQueue.tsx index bc03b176e8f..dd857e3b084 100644 --- a/desktop/app/src/utils/messageQueue.tsx +++ b/desktop/app/src/utils/messageQueue.tsx @@ -8,7 +8,7 @@ */ import {PersistedStateReducer, FlipperDevicePlugin} from '../plugin'; -import {State, MiddlewareAPI} from '../reducers/index'; +import type {State, MiddlewareAPI} from '../reducers/index'; import {setPluginState} from '../reducers/pluginStates'; import { clearMessageQueue, diff --git a/desktop/app/src/utils/onRegisterDevice.tsx b/desktop/app/src/utils/onRegisterDevice.tsx index 08784cb4c22..2ac2ba1a42a 100644 --- a/desktop/app/src/utils/onRegisterDevice.tsx +++ b/desktop/app/src/utils/onRegisterDevice.tsx @@ -7,16 +7,15 @@ * @format */ -import {Store} from '../reducers/index'; -import { +import type {Store} from '../reducers/index'; +import type { ClientPluginMap, DevicePluginMap, PluginDefinition, - isSandyPlugin, } from '../plugin'; import {setPluginState} from '../reducers/pluginStates'; -import BaseDevice from '../devices/BaseDevice'; -import {getPersistedState} from '../utils/pluginUtils'; +import type BaseDevice from '../devices/BaseDevice'; +import {getPersistedState, isSandyPlugin} from '../utils/pluginUtils'; export function registerDeviceCallbackOnPlugins( store: Store, diff --git a/desktop/app/src/utils/pluginUtils.tsx b/desktop/app/src/utils/pluginUtils.tsx index e52e931e2d9..6552742857d 100644 --- a/desktop/app/src/utils/pluginUtils.tsx +++ b/desktop/app/src/utils/pluginUtils.tsx @@ -12,7 +12,6 @@ import { FlipperBasePlugin, PluginDefinition, DevicePluginDefinition, - isSandyPlugin, ClientPluginDefinition, } from '../plugin'; import type {State} from '../reducers'; @@ -54,6 +53,12 @@ export function getPluginKey( return `unknown#${pluginID}`; } +export function isSandyPlugin( + plugin?: PluginDefinition | null, +): plugin is _SandyPluginDefinition { + return plugin instanceof _SandyPluginDefinition; +} + export function getPersistedState( pluginKey: string, persistingPlugin: typeof FlipperBasePlugin | null, diff --git a/desktop/flipper-plugin/src/plugin/DevicePlugin.tsx b/desktop/flipper-plugin/src/plugin/DevicePlugin.tsx index d1072a93d45..9c95df3e7d9 100644 --- a/desktop/flipper-plugin/src/plugin/DevicePlugin.tsx +++ b/desktop/flipper-plugin/src/plugin/DevicePlugin.tsx @@ -88,9 +88,10 @@ export class SandyDevicePluginInstance extends BasePluginInstance { flipperLib: FlipperLib, definition: SandyPluginDefinition, realDevice: RealFlipperDevice, + pluginKey: string, initialStates?: Record, ) { - super(flipperLib, definition, realDevice, initialStates); + super(flipperLib, definition, realDevice, pluginKey, initialStates); this.client = { ...this.createBasePluginClient(), isPluginAvailable(pluginId: string) { diff --git a/desktop/flipper-plugin/src/plugin/Plugin.tsx b/desktop/flipper-plugin/src/plugin/Plugin.tsx index 7dc7b6d1f60..edfa7df8383 100644 --- a/desktop/flipper-plugin/src/plugin/Plugin.tsx +++ b/desktop/flipper-plugin/src/plugin/Plugin.tsx @@ -148,9 +148,16 @@ export class SandyPluginInstance extends BasePluginInstance { flipperLib: FlipperLib, definition: SandyPluginDefinition, realClient: RealFlipperClient, + pluginKey: string, initialStates?: Record, ) { - super(flipperLib, definition, realClient.deviceSync, initialStates); + super( + flipperLib, + definition, + realClient.deviceSync, + pluginKey, + initialStates, + ); this.realClient = realClient; this.definition = definition; const self = this; diff --git a/desktop/flipper-plugin/src/plugin/PluginBase.tsx b/desktop/flipper-plugin/src/plugin/PluginBase.tsx index 5dc8c193656..ae46c68449a 100644 --- a/desktop/flipper-plugin/src/plugin/PluginBase.tsx +++ b/desktop/flipper-plugin/src/plugin/PluginBase.tsx @@ -23,6 +23,7 @@ type StateExportHandler = ( type StateImportHandler = (data: T) => void; export interface BasePluginClient { + readonly pluginKey: string; readonly device: Device; /** @@ -117,6 +118,9 @@ export abstract class BasePluginInstance { /** the device owning this plugin */ readonly device: Device; + /** the unique plugin key for this plugin instance, which is unique for this device/app?/pluginId combo */ + readonly pluginKey: string; + activated = false; destroyed = false; readonly events = new EventEmitter(); @@ -140,11 +144,13 @@ export abstract class BasePluginInstance { flipperLib: FlipperLib, definition: SandyPluginDefinition, realDevice: RealFlipperDevice, + pluginKey: string, initialStates?: Record, ) { this.flipperLib = flipperLib; this.definition = definition; this.initialStates = initialStates; + this.pluginKey = pluginKey; if (!realDevice) { throw new Error('Illegal State: Device has not yet been loaded'); } @@ -213,6 +219,7 @@ export abstract class BasePluginInstance { protected createBasePluginClient(): BasePluginClient { return { + pluginKey: this.pluginKey, device: this.device, onActivate: (cb) => { this.events.on('activate', batched(cb)); diff --git a/desktop/flipper-plugin/src/plugin/PluginContext.tsx b/desktop/flipper-plugin/src/plugin/PluginContext.tsx index 48ec9180906..c5018d65818 100644 --- a/desktop/flipper-plugin/src/plugin/PluginContext.tsx +++ b/desktop/flipper-plugin/src/plugin/PluginContext.tsx @@ -15,13 +15,20 @@ export const SandyPluginContext = createContext< SandyPluginInstance | SandyDevicePluginInstance | undefined >(undefined); -export function usePlugin< - Factory extends PluginFactory | DevicePluginFactory ->(plugin: Factory): ReturnType { +export function usePluginInstance(): + | SandyPluginInstance + | SandyDevicePluginInstance { const pluginInstance = useContext(SandyPluginContext); if (!pluginInstance) { - throw new Error('Plugin context not available'); + throw new Error('Sandy Plugin context not available'); } + return pluginInstance; +} + +export function usePlugin< + Factory extends PluginFactory | DevicePluginFactory +>(plugin: Factory): ReturnType { + const pluginInstance = usePluginInstance(); // In principle we don't *need* the plugin, but having it passed it makes sure the // return of this function is strongly typed, without the user needing to create it's own // context. diff --git a/desktop/flipper-plugin/src/test-utils/test-utils.tsx b/desktop/flipper-plugin/src/test-utils/test-utils.tsx index da2ecaa1a2e..7ab522200a2 100644 --- a/desktop/flipper-plugin/src/test-utils/test-utils.tsx +++ b/desktop/flipper-plugin/src/test-utils/test-utils.tsx @@ -234,6 +234,7 @@ export function startPlugin>( flipperUtils, definition, fakeFlipperClient, + `${fakeFlipperClient.id}#${definition.id}`, options?.initialState, ); @@ -313,6 +314,7 @@ export function startDevicePlugin( flipperLib, definition, testDevice, + `${testDevice.serial}#${definition.id}`, options?.initialState, ); diff --git a/desktop/flipper-plugin/src/ui/datatable/DataTable.tsx b/desktop/flipper-plugin/src/ui/datatable/DataTable.tsx index 8f05ad3b50f..904aa3bd7bd 100644 --- a/desktop/flipper-plugin/src/ui/datatable/DataTable.tsx +++ b/desktop/flipper-plugin/src/ui/datatable/DataTable.tsx @@ -44,8 +44,8 @@ import {tableContextMenuFactory} from './TableContextMenu'; import {Typography} from 'antd'; import {CoffeeOutlined, SearchOutlined} from '@ant-design/icons'; import {useAssertStableRef} from '../../utils/useAssertStableRef'; -import {TrackingScopeContext} from 'flipper-plugin/src/ui/Tracked'; import {Formatter} from '../DataFormatter'; +import {usePluginInstance} from '../../plugin/PluginContext'; interface DataTableProps { columns: DataTableColumn[]; @@ -103,7 +103,7 @@ export function DataTable( // lint disabled for conditional inclusion of a hook (_testHeight is asserted to be stable) // eslint-disable-next-line - const scope = props._testHeight ? "" : useContext(TrackingScopeContext); // TODO + plugin id + const scope = props._testHeight ? "" : usePluginInstance().pluginKey; const virtualizerRef = useRef(); const [state, dispatch] = useReducer( dataTableManagerReducer as DataTableReducer, diff --git a/desktop/flipper-plugin/src/ui/datatable/DataTableManager.tsx b/desktop/flipper-plugin/src/ui/datatable/DataTableManager.tsx index f0550f8fe80..d8edc3f0c7a 100644 --- a/desktop/flipper-plugin/src/ui/datatable/DataTableManager.tsx +++ b/desktop/flipper-plugin/src/ui/datatable/DataTableManager.tsx @@ -104,7 +104,6 @@ export type DataTableReducer = Reducer< >; export type DataTableDispatch = React.Dispatch>; -// TODO: make argu inference correct export const dataTableManagerReducer = produce(function ( draft: DataManagerState, action: DataManagerActions, @@ -208,7 +207,7 @@ export const dataTableManagerReducer = produce(function ( throw new Error('Unknown action ' + (action as any).type); } } -}) as any; // TODO: remove +}) as any; /** * Public only imperative convienience API for DataTable