diff --git a/desktop/app/src/Client.tsx b/desktop/app/src/Client.tsx index c1a864023..24f5bc0c5 100644 --- a/desktop/app/src/Client.tsx +++ b/desktop/app/src/Client.tsx @@ -31,10 +31,13 @@ import { _SandyPluginInstance, _getFlipperLibImplementation, } from 'flipper-plugin'; -import {flipperMessagesClientPlugin} from './utils/self-inspection/plugins/FlipperMessagesClientPlugin'; import {freeze} from 'immer'; import GK from './fb-stubs/GK'; import {message} from 'antd'; +import { + isFlipperMessageDebuggingEnabled, + registerFlipperDebugMessage, +} from './chrome/FlipperMessages'; type Plugins = Set; type PluginsArr = Array; @@ -384,11 +387,8 @@ export default class Client extends EventEmitter { const {id, method} = data; - if ( - data.params?.api != 'flipper-messages' && - flipperMessagesClientPlugin.isConnected() - ) { - flipperMessagesClientPlugin.newMessage({ + if (isFlipperMessageDebuggingEnabled()) { + registerFlipperDebugMessage({ device: this.deviceSync?.displayTitle(), app: this.query.app, flipperInternalMethod: method, @@ -416,7 +416,7 @@ export default class Client extends EventEmitter { const params: Params = data.params; const bytes = msg.length * 2; // string lengths are measured in UTF-16 units (not characters), so 2 bytes per char emitBytesReceived(params.api, bytes); - if (bytes > 5 * 1024 * 1024 && params.api !== 'flipper-messages') { + if (bytes > 5 * 1024 * 1024) { console.warn( `Plugin '${params.api}' received excessively large message for '${ params.method @@ -462,12 +462,7 @@ export default class Client extends EventEmitter { } } } - // TODO: Flipper debug as full client is overkill, clean up - if ( - !handled && - !isProduction() && - params.api !== 'flipper-messages' - ) { + if (!handled && !isProduction()) { console.warn(`Unhandled message ${params.api}.${params.method}`); } } @@ -597,8 +592,8 @@ export default class Client extends EventEmitter { this.onResponse(response, resolve, reject); - if (flipperMessagesClientPlugin.isConnected()) { - flipperMessagesClientPlugin.newMessage({ + if (isFlipperMessageDebuggingEnabled()) { + registerFlipperDebugMessage({ device: this.deviceSync?.displayTitle(), app: this.query.app, flipperInternalMethod: method, @@ -625,8 +620,8 @@ export default class Client extends EventEmitter { ); } - if (flipperMessagesClientPlugin.isConnected()) { - flipperMessagesClientPlugin.newMessage({ + if (isFlipperMessageDebuggingEnabled()) { + registerFlipperDebugMessage({ device: this.deviceSync?.displayTitle(), app: this.query.app, flipperInternalMethod: method, @@ -711,8 +706,8 @@ export default class Client extends EventEmitter { this.connection.fireAndForget({data: JSON.stringify(data)}); } - if (flipperMessagesClientPlugin.isConnected()) { - flipperMessagesClientPlugin.newMessage({ + if (isFlipperMessageDebuggingEnabled()) { + registerFlipperDebugMessage({ device: this.deviceSync?.displayTitle(), app: this.query.app, flipperInternalMethod: method, diff --git a/desktop/app/src/chrome/ConsoleLogs.tsx b/desktop/app/src/chrome/ConsoleLogs.tsx index ab197b19b..8c0e4ec16 100644 --- a/desktop/app/src/chrome/ConsoleLogs.tsx +++ b/desktop/app/src/chrome/ConsoleLogs.tsx @@ -8,7 +8,7 @@ */ import {useMemo} from 'react'; -import {Button, ButtonGroup, Layout} from '../ui'; +import {Button, Layout} from '../ui'; import React from 'react'; import {Console, Hook} from 'console-feed'; import type {Methods} from 'console-feed/lib/definitions/Methods'; @@ -92,13 +92,11 @@ export function ConsoleLogs() { return ( - - - - - + + + + + + + + + + + + + ); +} diff --git a/desktop/app/src/chrome/FlipperMessages.tsx b/desktop/app/src/chrome/FlipperMessages.tsx new file mode 100644 index 000000000..d3af8962b --- /dev/null +++ b/desktop/app/src/chrome/FlipperMessages.tsx @@ -0,0 +1,209 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +import { + DataInspector, + DataTable, + DataTableColumn, + Layout, + createState, + createDataSource, + DetailSidebar, + Panel, + theme, + styled, + useValue, +} from 'flipper-plugin'; +import {Button} from 'antd'; +import { + DeleteOutlined, + PauseCircleOutlined, + PlayCircleOutlined, +} from '@ant-design/icons'; +import React, {useCallback, useState} from 'react'; + +export type MessageInfo = { + time?: Date; + device?: string; + app: string; + flipperInternalMethod?: string; + plugin?: string; + pluginMethod?: string; + payload?: any; + direction: + | 'toClient:call' + | 'toClient:send' + | 'toFlipper:message' + | 'toFlipper:response'; +}; + +export interface MessageRow extends MessageInfo { + time: Date; +} + +const Placeholder = styled(Layout.Container)({ + center: true, + color: theme.textColorPlaceholder, + fontSize: 18, +}); + +function createRow(message: MessageInfo): MessageRow { + return { + ...message, + time: message.time == null ? new Date() : message.time, + }; +} + +const COLUMN_CONFIG: DataTableColumn[] = [ + { + key: 'time', + title: 'Time', + }, + { + key: 'device', + title: 'Device', + }, + { + key: 'app', + title: 'App', + }, + { + key: 'flipperInternalMethod', + title: 'Flipper Internal Method', + }, + { + key: 'plugin', + title: 'Plugin', + }, + { + key: 'pluginMethod', + title: 'Method', + }, + { + key: 'direction', + title: 'Direction', + }, +]; + +const flipperDebugMessages = createDataSource([], { + limit: 1024 * 10, + persist: 'messages', +}); +const flipperDebugMessagesEnabled = createState(false); + +export function registerFlipperDebugMessage(message: MessageInfo) { + if (flipperDebugMessagesEnabled.get()) { + flipperDebugMessages.append(createRow(message)); + } +} + +export function isFlipperMessageDebuggingEnabled(): boolean { + return flipperDebugMessagesEnabled.get(); +} + +// exposed for testing +export function setFlipperMessageDebuggingEnabled(value: boolean) { + flipperDebugMessagesEnabled.set(value); +} + +// exposed for testing +export function clearFlipperDebugMessages() { + flipperDebugMessages.clear(); +} + +// exposed for testing ONLY! +export function getFlipperDebugMessages() { + return flipperDebugMessages.records(); +} + +function Sidebar({selection}: {selection: undefined | MessageRow}) { + const renderExtra = (extra: any) => ( + + + + ); + + return ( + + {selection != null ? ( + renderExtra(selection.payload) + ) : ( + + Select a message to view details + + )} + + ); +} + +const PauseResumeButton = () => { + const paused = !useValue(flipperDebugMessagesEnabled); + + return ( + + ); +}; + +export function FlipperMessages() { + const [selection, setSelection] = useState(); + const paused = !useValue(flipperDebugMessagesEnabled); + + const clearTableButton = ( + + ); + + const renderEmpty = useCallback( + () => ( + + {paused ? ( + <> + Click to enable debugging Flipper messages between the Flipper + application and connected clients: + + ) : ( + 'Waiting for data...' + )} + + ), + [paused], + ); + + return ( + + + dataSource={flipperDebugMessages} + columns={COLUMN_CONFIG} + onSelect={setSelection} + enableAutoScroll + onRenderEmpty={renderEmpty} + extraActions={ + <> + + {clearTableButton} + + } + /> + + + ); +} diff --git a/desktop/plugins/public/flipper-messages/__tests__/flipper_messages.node.tsx b/desktop/app/src/chrome/__tests__/flipper_messages.node.tsx similarity index 56% rename from desktop/plugins/public/flipper-messages/__tests__/flipper_messages.node.tsx rename to desktop/app/src/chrome/__tests__/flipper_messages.node.tsx index 9c89f3301..d4b773702 100644 --- a/desktop/plugins/public/flipper-messages/__tests__/flipper_messages.node.tsx +++ b/desktop/app/src/chrome/__tests__/flipper_messages.node.tsx @@ -7,45 +7,67 @@ * @format */ -import {TestUtils} from 'flipper-plugin'; +import * as React from 'react'; +import {act, render} from '@testing-library/react'; -import * as Plugin from '../'; -import {MessageRow} from '../'; +import { + clearFlipperDebugMessages, + FlipperMessages, + getFlipperDebugMessages, + MessageRow, + registerFlipperDebugMessage, + setFlipperMessageDebuggingEnabled, +} from '../FlipperMessages'; const fixRowTimestamps = (r: MessageRow): MessageRow => ({ ...r, time: new Date(Date.UTC(0, 0, 0, 0, 0, 0)), }); +beforeEach(() => { + clearFlipperDebugMessages(); + setFlipperMessageDebuggingEnabled(true); +}); + +afterEach(() => { + clearFlipperDebugMessages(); + setFlipperMessageDebuggingEnabled(false); +}); + test('It can store rows', () => { - const {instance, ...plugin} = TestUtils.startPlugin(Plugin); - - expect(instance.rows.records()).toEqual([]); - expect(instance.highlightedRow.get()).toBeUndefined(); - - plugin.sendEvent('newMessage', { + registerFlipperDebugMessage({ app: 'Flipper', - direction: 'toFlipper', + direction: 'toFlipper:message', }); - plugin.sendEvent('newMessage', { + registerFlipperDebugMessage({ app: 'FB4A', - direction: 'toClient', + direction: 'toClient:call', device: 'Android Phone', payload: {hello: 'world'}, }); - expect(instance.rows.records().map(fixRowTimestamps)).toMatchInlineSnapshot(` + setFlipperMessageDebuggingEnabled(false); + + registerFlipperDebugMessage({ + app: 'FB4A', + direction: 'toClient:call', + device: 'Android PhoneTEst', + payload: {hello: 'world'}, + }); + + expect(getFlipperDebugMessages().map(fixRowTimestamps)) + .toMatchInlineSnapshot(` Array [ Object { "app": "Flipper", - "direction": "toFlipper", + "direction": "toFlipper:message", "time": 1899-12-31T00:00:00.000Z, }, Object { "app": "FB4A", "device": "Android Phone", - "direction": "toClient", + "direction": "toClient:call", "payload": Object { "hello": "world", }, @@ -56,61 +78,43 @@ test('It can store rows', () => { }); test('It can clear', () => { - const {instance, ...plugin} = TestUtils.startPlugin(Plugin); - - expect(instance.rows.records()).toEqual([]); - expect(instance.highlightedRow.get()).toBeUndefined(); - - plugin.sendEvent('newMessage', { + registerFlipperDebugMessage({ app: 'Flipper', - direction: 'toFlipper', + direction: 'toFlipper:message', }); - instance.clear(); - - const newRows = instance.rows.records().map(fixRowTimestamps); - expect(newRows).toEqual([]); -}); - -test('It can highlight a row', () => { - const {instance, ...plugin} = TestUtils.startPlugin(Plugin); - - plugin.sendEvent('newMessage', { - app: 'Flipper', - direction: 'toFlipper', - }); - - instance.setHighlightedRow(instance.rows.records()[0]); - - expect(instance.rows.records()).toHaveLength(1); - expect(instance.highlightedRow.get()?.app).toEqual('Flipper'); + clearFlipperDebugMessages(); + expect(getFlipperDebugMessages()).toEqual([]); }); test('It can render empty', async () => { - const {renderer} = TestUtils.renderPlugin(Plugin); + const renderer = render(); // Default message without any highlighted rows. expect( await renderer.findByText('Select a message to view details'), ).not.toBeNull(); + renderer.unmount(); }); test('It can render rows', async () => { - const {renderer, ...plugin} = TestUtils.renderPlugin(Plugin); + const renderer = render(); - plugin.sendEvent('newMessage', { - time: new Date(0, 0, 0, 0, 0, 0), - app: 'Flipper', - direction: 'toFlipper', - }); + act(() => { + registerFlipperDebugMessage({ + time: new Date(0, 0, 0, 0, 0, 0), + app: 'Flipper', + direction: 'toFlipper:message', + }); - plugin.sendEvent('newMessage', { - time: new Date(0, 0, 0, 0, 0, 0), - app: 'FB4A', - direction: 'toClient', - device: 'Android Phone', - flipperInternalMethod: 'unique-string', - payload: {hello: 'world'}, + registerFlipperDebugMessage({ + time: new Date(0, 0, 0, 0, 0, 0), + app: 'FB4A', + direction: 'toClient:send', + device: 'Android Phone', + flipperInternalMethod: 'unique-string', + payload: {hello: 'world'}, + }); }); expect((await renderer.findByText('unique-string')).parentElement) @@ -154,8 +158,10 @@ test('It can render rows', async () => { class="css-1vr131n-TableBodyColumnContainer e1luu51r0" width="14%" > - toClient + toClient:send `); + + renderer.unmount(); }); diff --git a/desktop/app/src/sandy-chrome/SandyApp.tsx b/desktop/app/src/sandy-chrome/SandyApp.tsx index 0c1f1196a..a9d2a4574 100644 --- a/desktop/app/src/sandy-chrome/SandyApp.tsx +++ b/desktop/app/src/sandy-chrome/SandyApp.tsx @@ -16,7 +16,7 @@ import {Logger} from '../fb-interfaces/Logger'; import {LeftRail} from './LeftRail'; import {useStore, useDispatch} from '../utils/useStore'; -import {ConsoleLogs} from '../chrome/ConsoleLogs'; +import {FlipperDevTools} from '../chrome/FlipperDevTools'; import {setStaticView} from '../reducers/connections'; import { ACTIVE_SHEET_CHANGELOG_RECENT_ONLY, @@ -79,7 +79,7 @@ export function SandyApp() { } switch (newSelection) { case 'flipperlogs': - dispatch(setStaticView(ConsoleLogs)); + dispatch(setStaticView(FlipperDevTools)); break; default: } diff --git a/desktop/app/src/server.tsx b/desktop/app/src/server.tsx index 57f081c4b..19f15da8f 100644 --- a/desktop/app/src/server.tsx +++ b/desktop/app/src/server.tsx @@ -37,7 +37,6 @@ import {WebsocketClientFlipperConnection} from './utils/js-client-server-utils/w import querystring from 'querystring'; import {IncomingMessage} from 'http'; import ws from 'ws'; -import {initSelfInpector} from './utils/self-inspection/selfInspectionUtils'; import DummyDevice from './devices/DummyDevice'; import BaseDevice from './devices/BaseDevice'; import {sideEffect} from './utils/sideEffect'; @@ -106,10 +105,6 @@ class Server extends EventEmitter { } init() { - if (process.env.NODE_ENV === 'development') { - initSelfInpector(this.store, this.logger, this, this.connections); - } - const {insecure, secure} = this.store.getState().application.serverPorts; this.initialisePromise = this.certificateProvider .loadSecureServerConfig() diff --git a/desktop/app/src/utils/notifications.tsx b/desktop/app/src/utils/notifications.tsx index 29b5f61e5..7bcde27ea 100644 --- a/desktop/app/src/utils/notifications.tsx +++ b/desktop/app/src/utils/notifications.tsx @@ -9,7 +9,7 @@ import {notification, Typography} from 'antd'; import React from 'react'; -import {ConsoleLogs} from '../chrome/ConsoleLogs'; +import {FlipperDevTools} from '../chrome/FlipperDevTools'; import {setStaticView} from '../reducers/connections'; import {getStore} from '../store'; import {Layout} from '../ui'; @@ -29,7 +29,7 @@ export function showErrorNotification(message: string, description?: string) { See{' '} { - getStore().dispatch(setStaticView(ConsoleLogs)); + getStore().dispatch(setStaticView(FlipperDevTools)); notification.close(key); }}> logs diff --git a/desktop/app/src/utils/self-inspection/plugins/FlipperMessagesClientPlugin.tsx b/desktop/app/src/utils/self-inspection/plugins/FlipperMessagesClientPlugin.tsx deleted file mode 100644 index f4e76d0bc..000000000 --- a/desktop/app/src/utils/self-inspection/plugins/FlipperMessagesClientPlugin.tsx +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - */ - -import {FlipperConnection, FlipperPlugin} from 'flipper-client-sdk'; - -export type MessageInfo = { - device?: string; - app: string; - flipperInternalMethod?: string; - plugin?: string; - pluginMethod?: string; - payload?: any; - direction: - | 'toClient:call' - | 'toClient:send' - | 'toFlipper:message' - | 'toFlipper:response'; -}; - -export class FlipperMessagesClientPlugin implements FlipperPlugin { - protected connection: FlipperConnection | null = null; - - onConnect(connection: FlipperConnection): void { - this.connection = connection; - } - - onDisconnect(): void { - this.connection = null; - } - - getId(): string { - return 'flipper-messages'; - } - - runInBackground(): boolean { - return true; - } - - newMessage(message: MessageInfo) { - this.connection?.send('newMessage', message); - } - - isConnected() { - return this.connection != null; - } -} - -export const flipperMessagesClientPlugin = new FlipperMessagesClientPlugin(); diff --git a/desktop/app/src/utils/self-inspection/selfInspectionClient.tsx b/desktop/app/src/utils/self-inspection/selfInspectionClient.tsx deleted file mode 100644 index 8a158020d..000000000 --- a/desktop/app/src/utils/self-inspection/selfInspectionClient.tsx +++ /dev/null @@ -1,117 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - */ - -import {FlipperClientConnection} from '../../Client'; -import {Flowable, Single} from 'rsocket-flowable'; -import {Payload, ConnectionStatus, ISubscriber} from 'rsocket-types'; - -import {FlipperClient} from 'flipper-client-sdk'; - -// somehow linter isn't happy with next import so type definitions are copied -// import {IFutureSubject} from 'rsocket-flowable/Single'; - -type CancelCallback = () => void; - -interface IFutureSubject { - onComplete: (value: T) => void; - onError: (error: Error) => void; - onSubscribe: (cancel: CancelCallback | null | undefined) => void; -} - -export class SelfInspectionFlipperClient - extends FlipperClient - implements FlipperClientConnection -{ - connStatusSubscribers: Set> = new Set(); - connStatus: ConnectionStatus = {kind: 'CONNECTED'}; - - connectionStatus(): Flowable { - return new Flowable((subscriber) => { - subscriber.onSubscribe({ - cancel: () => { - this.connStatusSubscribers.delete(subscriber); - }, - request: (_) => { - this.connStatusSubscribers.add(subscriber); - subscriber.onNext(this.connStatus); - }, - }); - }); - } - - close(): void { - this.connStatus = {kind: 'CLOSED'}; - this.connStatusSubscribers.forEach((subscriber) => { - subscriber.onNext(this.connStatus); - }); - } - - fireAndForget(payload: Payload): void { - if (payload.data == null) { - return; - } - const message = JSON.parse(payload.data) as { - method: string; - id: number; - params: any; - }; - this.onMessageReceived(message); - } - - activeRequests = new Map>>(); - - requestResponse(payload: Payload): Single> { - return new Single((subscriber) => { - subscriber.onSubscribe(() => {}); - if (payload.data == null) { - subscriber.onError(new Error('empty payload')); - return; - } - const message = JSON.parse(payload.data) as { - method: string; - id: number; - params: any; - }; - this.activeRequests.set(message.id, subscriber); - this.onMessageReceived(message); - }); - } - - // Client methods - - messagesHandler: ((message: any) => void) | undefined; - - start(_appName: string): void { - this.onConnect(); - } - - stop(): void {} - - sendData(payload: any): void { - if (payload['success'] != null) { - const message = payload as {id: number; success: unknown}; - const sub = this.activeRequests.get(message.id); - sub?.onComplete({data: JSON.stringify(message)}); - this.activeRequests.delete(message.id); - return; - } - - this.messagesHandler && this.messagesHandler(payload); - } - - isAvailable(): boolean { - return true; - } - - subscibeForClientMessages(handler: (message: any) => void) { - this.messagesHandler = handler; - } -} - -export const selfInspectionClient = new SelfInspectionFlipperClient(); diff --git a/desktop/app/src/utils/self-inspection/selfInspectionUtils.tsx b/desktop/app/src/utils/self-inspection/selfInspectionUtils.tsx deleted file mode 100644 index e9957ee69..000000000 --- a/desktop/app/src/utils/self-inspection/selfInspectionUtils.tsx +++ /dev/null @@ -1,94 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - */ - -import Client, {ClientQuery} from '../../Client'; -import {FlipperClientConnection} from '../../Client'; -import {Store} from '../../reducers'; -import {Logger} from '../../fb-interfaces/Logger'; - -import Server from '../../server'; -import {buildClientId} from '../clientUtils'; -import {selfInspectionClient} from './selfInspectionClient'; -import {flipperMessagesClientPlugin} from './plugins/FlipperMessagesClientPlugin'; -import {destroyDevice} from '../../reducers/connections'; - -export function initSelfInpector( - store: Store, - logger: Logger, - flipperServer: Server, - flipperConnections: Map< - string, - { - connection: FlipperClientConnection | null | undefined; - client: Client; - } - >, -) { - const appName = 'Flipper'; - - selfInspectionClient.addPlugin(flipperMessagesClientPlugin); - const hostDevice = store - .getState() - .connections.devices.find((d) => d.serial === ''); - if (!hostDevice) { - console.error('Failed to find host device for self inspector'); - return; - } - - const query: ClientQuery = { - app: appName, - os: 'MacOS', - device: 'emulator', - device_id: '', - sdk_version: 4, - }; - const clientId = buildClientId(query); - - const client = new Client( - clientId, - query, - selfInspectionClient, - logger, - store, - undefined, - hostDevice, - ); - - flipperConnections.set(clientId, { - connection: selfInspectionClient, - client: client, - }); - - selfInspectionClient.connectionStatus().subscribe({ - onNext(payload) { - if (payload.kind == 'ERROR' || payload.kind == 'CLOSED') { - console.debug(`Device disconnected ${client.id}`, 'server'); - flipperServer.removeConnection(client.id); - destroyDevice(store, logger, client.id); - } - }, - onSubscribe(subscription) { - subscription.request(Number.MAX_SAFE_INTEGER); - }, - }); - - client.init().then(() => { - flipperServer.emit('new-client', client); - flipperServer.emit('clients-change'); - client.emit('plugins-change'); - - selfInspectionClient.subscibeForClientMessages((payload: any) => { - // let's break the possible recursion problems here - // for example we want to send init plugin message, but store state is being updated when we enable plugins - setImmediate(() => { - client.onMessage(JSON.stringify(payload)); - }); - }); - }); -} diff --git a/desktop/flipper-plugin/src/plugin/PluginContext.tsx b/desktop/flipper-plugin/src/plugin/PluginContext.tsx index 93b2aa6ba..a0acfc22f 100644 --- a/desktop/flipper-plugin/src/plugin/PluginContext.tsx +++ b/desktop/flipper-plugin/src/plugin/PluginContext.tsx @@ -25,6 +25,13 @@ export function usePluginInstance(): return pluginInstance; } +export function usePluginInstanceMaybe(): + | SandyPluginInstance + | SandyDevicePluginInstance + | undefined { + return useContext(SandyPluginContext); +} + export function usePlugin< Factory extends PluginFactory | DevicePluginFactory, >(plugin: Factory): ReturnType { diff --git a/desktop/flipper-plugin/src/ui/data-table/DataTable.tsx b/desktop/flipper-plugin/src/ui/data-table/DataTable.tsx index 1ea9a8340..f270509dd 100644 --- a/desktop/flipper-plugin/src/ui/data-table/DataTable.tsx +++ b/desktop/flipper-plugin/src/ui/data-table/DataTable.tsx @@ -48,7 +48,7 @@ import {Typography} from 'antd'; import {CoffeeOutlined, SearchOutlined, PushpinFilled} from '@ant-design/icons'; import {useAssertStableRef} from '../../utils/useAssertStableRef'; import {Formatter} from '../DataFormatter'; -import {usePluginInstance} from '../../plugin/PluginContext'; +import {usePluginInstanceMaybe} from '../../plugin/PluginContext'; import {debounce} from 'lodash'; import {useInUnitTest} from '../../utils/useInUnitTest'; import {createDataSource} from 'flipper-plugin/src/state/createDataSource'; @@ -142,7 +142,7 @@ export function DataTable( const isUnitTest = useInUnitTest(); // eslint-disable-next-line - const scope = isUnitTest ? "" : usePluginInstance().pluginKey; + const scope = isUnitTest ? "" : usePluginInstanceMaybe()?.pluginKey ?? ""; const virtualizerRef = useRef(); const [tableState, dispatch] = useReducer( dataTableManagerReducer as DataTableReducer, diff --git a/desktop/plugins/public/flipper-messages/index.tsx b/desktop/plugins/public/flipper-messages/index.tsx deleted file mode 100644 index 214b111a6..000000000 --- a/desktop/plugins/public/flipper-messages/index.tsx +++ /dev/null @@ -1,163 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - */ - -import { - DataInspector, - DataTable, - DataTableColumn, - Layout, - createState, - PluginClient, - usePlugin, - useValue, - createDataSource, - DetailSidebar, - Panel, - theme, - styled, -} from 'flipper-plugin'; -import {Button} from 'antd'; -import {DeleteOutlined} from '@ant-design/icons'; -import React from 'react'; - -export interface MessageInfo { - time?: Date; - device?: string; - app: string; - flipperInternalMethod?: string; - plugin?: string; - pluginMethod?: string; - payload?: any; - direction: 'toClient' | 'toFlipper'; -} - -export interface MessageRow extends MessageInfo { - time: Date; -} - -const Placeholder = styled(Layout.Container)({ - center: true, - color: theme.textColorPlaceholder, - fontSize: 18, -}); - -function createRow(message: MessageInfo): MessageRow { - return { - ...message, - time: message.time == null ? new Date() : message.time, - }; -} - -type Events = { - newMessage: MessageInfo; -}; - -const COLUMN_CONFIG: DataTableColumn[] = [ - { - key: 'time', - title: 'Time', - }, - { - key: 'device', - title: 'Device', - }, - { - key: 'app', - title: 'App', - }, - { - key: 'flipperInternalMethod', - title: 'Flipper Internal Method', - }, - { - key: 'plugin', - title: 'Plugin', - }, - { - key: 'pluginMethod', - title: 'Method', - }, - { - key: 'direction', - title: 'Direction', - }, -]; - -export function plugin(client: PluginClient) { - const highlightedRow = createState(); - const rows = createDataSource([], { - limit: 1024 * 10, - persist: 'messages', - }); - - const setHighlightedRow = (record: MessageRow) => { - highlightedRow.set(record); - }; - - const clear = () => { - highlightedRow.set(undefined); - rows.clear(); - }; - - client.onMessage('newMessage', (payload) => { - rows.append(createRow(payload)); - }); - - return { - rows, - highlightedRow, - setHighlightedRow, - clear, - }; -} - -function Sidebar() { - const instance = usePlugin(plugin); - const message = useValue(instance.highlightedRow); - - const renderExtra = (extra: any) => ( - - - - ); - - return ( - - {message != null ? ( - renderExtra(message.payload) - ) : ( - - Select a message to view details - - )} - - ); -} - -export function Component() { - const instance = usePlugin(plugin); - - const clearTableButton = ( - - ); - - return ( - - - dataSource={instance.rows} - columns={COLUMN_CONFIG} - onSelect={instance.setHighlightedRow} - extraActions={clearTableButton} - /> - - - ); -} diff --git a/desktop/plugins/public/flipper-messages/package.json b/desktop/plugins/public/flipper-messages/package.json deleted file mode 100644 index b5e1f1f71..000000000 --- a/desktop/plugins/public/flipper-messages/package.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "$schema": "https://fbflipper.com/schemas/plugin-package/v2.json", - "name": "flipper-plugin-flipper-messages", - "id": "flipper-messages", - "title": "Flipper Messages", - "icon": "bird", - "version": "0.0.0", - "description": "Flipper self inspection: Messages to and from client", - "main": "dist/bundle.js", - "flipperBundlerEntry": "index.tsx", - "license": "MIT", - "keywords": [ - "flipper-plugin" - ], - "bugs": { - "url": "https://github.com/facebook/flipper/issues" - }, - "scripts": { - "lint": "flipper-pkg lint", - "build": "flipper-pkg bundle", - "watch": "flipper-pkg bundle --watch", - "prepack": "flipper-pkg lint && flipper-pkg bundle --production" - }, - "peerDependencies": { - "flipper": "*", - "flipper-pkg": "*", - "flipper-plugin": "*" - } -}