From 4463e7ede26e884f7a4b27fd44ab3cb6a9de4d16 Mon Sep 17 00:00:00 2001 From: Michel Weststrate Date: Wed, 22 Sep 2021 09:01:29 -0700 Subject: [PATCH] Restore metro functionality [4/n] Summary: Restored Metro functionality; progress reports, metro logs, RN/Hermes debugging, reload / dev menu button Reviewed By: passy Differential Revision: D31055958 fbshipit-source-id: c243035c343c14718a9afe275c8f5f36a1aa3a94 --- desktop/app/src/__tests__/disconnect.node.tsx | 6 ++--- desktop/app/src/chrome/MetroButton.tsx | 23 +++++++++++++------ desktop/app/src/devices/BaseDevice.tsx | 4 ++++ desktop/app/src/reducers/connections.tsx | 4 +++- .../src/server/devices/metro/MetroDevice.tsx | 3 --- .../plugins/public/reactdevtools/index.tsx | 13 +++++------ 6 files changed, 32 insertions(+), 21 deletions(-) diff --git a/desktop/app/src/__tests__/disconnect.node.tsx b/desktop/app/src/__tests__/disconnect.node.tsx index ae986c822..e1b9bae96 100644 --- a/desktop/app/src/__tests__/disconnect.node.tsx +++ b/desktop/app/src/__tests__/disconnect.node.tsx @@ -14,6 +14,7 @@ import { createState, DevicePluginClient, PluginClient, + sleep, } from 'flipper-plugin'; import {handleClientConnected} from '../dispatcher/flipperServer'; import {TestDevice} from '../test-utils/TestDevice'; @@ -89,9 +90,7 @@ test('New device with same serial removes & cleans the old one', async () => { }, }, ); - const {device, store, logger} = await createMockFlipperWithPlugin( - deviceplugin, - ); + const {device, store} = await createMockFlipperWithPlugin(deviceplugin); const instance = device.sandyPluginStates.get(deviceplugin.id)!; @@ -116,6 +115,7 @@ test('New device with same serial removes & cleans the old one', async () => { store.getState().connections.enabledDevicePlugins, ); + await sleep(100); expect(device.isArchived).toBe(false); expect(device.connected.get()).toBe(false); expect(instance.instanceApi.destroy).toBeCalledTimes(1); diff --git a/desktop/app/src/chrome/MetroButton.tsx b/desktop/app/src/chrome/MetroButton.tsx index a37284e6d..950dd4a0e 100644 --- a/desktop/app/src/chrome/MetroButton.tsx +++ b/desktop/app/src/chrome/MetroButton.tsx @@ -8,24 +8,23 @@ */ import React, {useCallback, useEffect, useState} from 'react'; -import MetroDevice, { - MetroReportableEvent, -} from '../server/devices/metro/MetroDevice'; +import {MetroReportableEvent} from '../server/devices/metro/MetroDevice'; import {useStore} from '../utils/useStore'; import {Button as AntButton} from 'antd'; import {MenuOutlined, ReloadOutlined} from '@ant-design/icons'; import {theme} from 'flipper-plugin'; +import BaseDevice from '../devices/BaseDevice'; export default function MetroButton() { const device = useStore((state) => state.connections.devices.find( (device) => device.os === 'Metro' && device.connected.get(), ), - ) as MetroDevice | undefined; + ) as BaseDevice | undefined; const sendCommand = useCallback( (command: string) => { - device?.sendCommand(command); + device?.sendMetroCommand(command); }, [device], ); @@ -50,9 +49,19 @@ export default function MetroButton() { setProgress(event.transformedFileCount / event.totalFileCount); } } - device.metroEventEmitter.on('event', metroEventListener); + + const handle = device.addLogListener((l) => { + if (l.tag !== 'client_log') { + try { + metroEventListener(JSON.parse(l.message)); + } catch (e) { + console.warn('Failed to parse metro message: ', l, e); + } + } + }); + return () => { - device.metroEventEmitter.off('event', metroEventListener); + device.removeLogListener(handle); }; }, [device]); diff --git a/desktop/app/src/devices/BaseDevice.tsx b/desktop/app/src/devices/BaseDevice.tsx index e50c51da9..76bf85b50 100644 --- a/desktop/app/src/devices/BaseDevice.tsx +++ b/desktop/app/src/devices/BaseDevice.tsx @@ -229,6 +229,10 @@ export default class BaseDevice { return this.flipperServer.exec('device-shell-exec', this.serial, command); } + async sendMetroCommand(command: string): Promise { + return this.flipperServer.exec('metro-command', this.serial, command); + } + supportsPlugin(plugin: PluginDefinition | PluginDetails) { let pluginDetails: PluginDetails; if (plugin instanceof _SandyPluginDefinition) { diff --git a/desktop/app/src/reducers/connections.tsx b/desktop/app/src/reducers/connections.tsx index 2f3d48da3..138b488de 100644 --- a/desktop/app/src/reducers/connections.tsx +++ b/desktop/app/src/reducers/connections.tsx @@ -250,7 +250,9 @@ export default (state: State = INITAL_STATE, action: Actions): State => { `Tried to replace still connected device '${d.serial}' with a new instance`, ); } - d.destroy(); + setImmediate(() => { + d.destroy(); + }); newDevices[existing] = payload; } else { newDevices.push(payload); diff --git a/desktop/app/src/server/devices/metro/MetroDevice.tsx b/desktop/app/src/server/devices/metro/MetroDevice.tsx index 8132fe41e..92323344b 100644 --- a/desktop/app/src/server/devices/metro/MetroDevice.tsx +++ b/desktop/app/src/server/devices/metro/MetroDevice.tsx @@ -8,7 +8,6 @@ */ import {LogLevel} from 'flipper-plugin'; -import {EventEmitter} from 'events'; import util from 'util'; import {FlipperServerImpl} from '../../FlipperServerImpl'; import {ServerDevice} from '../ServerDevice'; @@ -142,7 +141,6 @@ function getLoglevelFromMessageType( export default class MetroDevice extends ServerDevice { ws?: WebSocket; - metroEventEmitter = new EventEmitter(); constructor( flipperServer: FlipperServerImpl, @@ -190,7 +188,6 @@ export default class MetroDevice extends ServerDevice { }); } } - this.metroEventEmitter.emit('event', message); }; sendCommand(command: string, params?: any) { diff --git a/desktop/plugins/public/reactdevtools/index.tsx b/desktop/plugins/public/reactdevtools/index.tsx index d2cc67a83..60a48053f 100644 --- a/desktop/plugins/public/reactdevtools/index.tsx +++ b/desktop/plugins/public/reactdevtools/index.tsx @@ -30,8 +30,7 @@ const CONNECTED = 'DevTools connected'; const DEV_TOOLS_PORT = 8097; // hardcoded in RN interface MetroDevice { - ws?: WebSocket; - sendCommand(command: string, params?: any): void; + sendMetroCommand(command: string, params?: any): void; } function findGlobalDevTools(): Promise { @@ -66,7 +65,7 @@ enum ConnectionStatus { export function devicePlugin(client: DevicePluginClient) { const metroDevice: MetroDevice = client.device.realDevice; - if (!metroDevice.sendCommand || !('ws' in metroDevice)) { + if (!metroDevice.sendMetroCommand) { throw new Error('Invalid metroDevice'); } @@ -196,12 +195,12 @@ export function devicePlugin(client: DevicePluginClient) { return; // Waiting for connection, but we do have an active Metro connection, lets force a reload to enter Dev Mode on app // prettier-ignore - case connectionStatus.get() === ConnectionStatus.Initializing && !!metroDevice?.ws: + case connectionStatus.get() === ConnectionStatus.Initializing: setStatus( ConnectionStatus.WaitingForReload, "Sending 'reload' to Metro to force the DevTools to connect...", ); - metroDevice!.sendCommand('reload'); + metroDevice!.sendMetroCommand('reload'); startPollForConnection(2000); return; // Waiting for initial connection, but no WS bridge available @@ -295,12 +294,12 @@ export function Component() { {statusMessage} ) : null} {(connectionStatus === ConnectionStatus.WaitingForReload && - instance.metroDevice?.ws) || + instance.metroDevice) || connectionStatus === ConnectionStatus.Error ? (