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
This commit is contained in:
committed by
Facebook GitHub Bot
parent
3428ce2968
commit
4463e7ede2
@@ -14,6 +14,7 @@ import {
|
|||||||
createState,
|
createState,
|
||||||
DevicePluginClient,
|
DevicePluginClient,
|
||||||
PluginClient,
|
PluginClient,
|
||||||
|
sleep,
|
||||||
} from 'flipper-plugin';
|
} from 'flipper-plugin';
|
||||||
import {handleClientConnected} from '../dispatcher/flipperServer';
|
import {handleClientConnected} from '../dispatcher/flipperServer';
|
||||||
import {TestDevice} from '../test-utils/TestDevice';
|
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(
|
const {device, store} = await createMockFlipperWithPlugin(deviceplugin);
|
||||||
deviceplugin,
|
|
||||||
);
|
|
||||||
|
|
||||||
const instance = device.sandyPluginStates.get(deviceplugin.id)!;
|
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,
|
store.getState().connections.enabledDevicePlugins,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await sleep(100);
|
||||||
expect(device.isArchived).toBe(false);
|
expect(device.isArchived).toBe(false);
|
||||||
expect(device.connected.get()).toBe(false);
|
expect(device.connected.get()).toBe(false);
|
||||||
expect(instance.instanceApi.destroy).toBeCalledTimes(1);
|
expect(instance.instanceApi.destroy).toBeCalledTimes(1);
|
||||||
|
|||||||
@@ -8,24 +8,23 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React, {useCallback, useEffect, useState} from 'react';
|
import React, {useCallback, useEffect, useState} from 'react';
|
||||||
import MetroDevice, {
|
import {MetroReportableEvent} from '../server/devices/metro/MetroDevice';
|
||||||
MetroReportableEvent,
|
|
||||||
} from '../server/devices/metro/MetroDevice';
|
|
||||||
import {useStore} from '../utils/useStore';
|
import {useStore} from '../utils/useStore';
|
||||||
import {Button as AntButton} from 'antd';
|
import {Button as AntButton} from 'antd';
|
||||||
import {MenuOutlined, ReloadOutlined} from '@ant-design/icons';
|
import {MenuOutlined, ReloadOutlined} from '@ant-design/icons';
|
||||||
import {theme} from 'flipper-plugin';
|
import {theme} from 'flipper-plugin';
|
||||||
|
import BaseDevice from '../devices/BaseDevice';
|
||||||
|
|
||||||
export default function MetroButton() {
|
export default function MetroButton() {
|
||||||
const device = useStore((state) =>
|
const device = useStore((state) =>
|
||||||
state.connections.devices.find(
|
state.connections.devices.find(
|
||||||
(device) => device.os === 'Metro' && device.connected.get(),
|
(device) => device.os === 'Metro' && device.connected.get(),
|
||||||
),
|
),
|
||||||
) as MetroDevice | undefined;
|
) as BaseDevice | undefined;
|
||||||
|
|
||||||
const sendCommand = useCallback(
|
const sendCommand = useCallback(
|
||||||
(command: string) => {
|
(command: string) => {
|
||||||
device?.sendCommand(command);
|
device?.sendMetroCommand(command);
|
||||||
},
|
},
|
||||||
[device],
|
[device],
|
||||||
);
|
);
|
||||||
@@ -50,9 +49,19 @@ export default function MetroButton() {
|
|||||||
setProgress(event.transformedFileCount / event.totalFileCount);
|
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 () => {
|
return () => {
|
||||||
device.metroEventEmitter.off('event', metroEventListener);
|
device.removeLogListener(handle);
|
||||||
};
|
};
|
||||||
}, [device]);
|
}, [device]);
|
||||||
|
|
||||||
|
|||||||
@@ -229,6 +229,10 @@ export default class BaseDevice {
|
|||||||
return this.flipperServer.exec('device-shell-exec', this.serial, command);
|
return this.flipperServer.exec('device-shell-exec', this.serial, command);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async sendMetroCommand(command: string): Promise<void> {
|
||||||
|
return this.flipperServer.exec('metro-command', this.serial, command);
|
||||||
|
}
|
||||||
|
|
||||||
supportsPlugin(plugin: PluginDefinition | PluginDetails) {
|
supportsPlugin(plugin: PluginDefinition | PluginDetails) {
|
||||||
let pluginDetails: PluginDetails;
|
let pluginDetails: PluginDetails;
|
||||||
if (plugin instanceof _SandyPluginDefinition) {
|
if (plugin instanceof _SandyPluginDefinition) {
|
||||||
|
|||||||
@@ -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`,
|
`Tried to replace still connected device '${d.serial}' with a new instance`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
setImmediate(() => {
|
||||||
d.destroy();
|
d.destroy();
|
||||||
|
});
|
||||||
newDevices[existing] = payload;
|
newDevices[existing] = payload;
|
||||||
} else {
|
} else {
|
||||||
newDevices.push(payload);
|
newDevices.push(payload);
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {LogLevel} from 'flipper-plugin';
|
import {LogLevel} from 'flipper-plugin';
|
||||||
import {EventEmitter} from 'events';
|
|
||||||
import util from 'util';
|
import util from 'util';
|
||||||
import {FlipperServerImpl} from '../../FlipperServerImpl';
|
import {FlipperServerImpl} from '../../FlipperServerImpl';
|
||||||
import {ServerDevice} from '../ServerDevice';
|
import {ServerDevice} from '../ServerDevice';
|
||||||
@@ -142,7 +141,6 @@ function getLoglevelFromMessageType(
|
|||||||
|
|
||||||
export default class MetroDevice extends ServerDevice {
|
export default class MetroDevice extends ServerDevice {
|
||||||
ws?: WebSocket;
|
ws?: WebSocket;
|
||||||
metroEventEmitter = new EventEmitter();
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
flipperServer: FlipperServerImpl,
|
flipperServer: FlipperServerImpl,
|
||||||
@@ -190,7 +188,6 @@ export default class MetroDevice extends ServerDevice {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.metroEventEmitter.emit('event', message);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
sendCommand(command: string, params?: any) {
|
sendCommand(command: string, params?: any) {
|
||||||
|
|||||||
@@ -30,8 +30,7 @@ const CONNECTED = 'DevTools connected';
|
|||||||
const DEV_TOOLS_PORT = 8097; // hardcoded in RN
|
const DEV_TOOLS_PORT = 8097; // hardcoded in RN
|
||||||
|
|
||||||
interface MetroDevice {
|
interface MetroDevice {
|
||||||
ws?: WebSocket;
|
sendMetroCommand(command: string, params?: any): void;
|
||||||
sendCommand(command: string, params?: any): void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function findGlobalDevTools(): Promise<string | undefined> {
|
function findGlobalDevTools(): Promise<string | undefined> {
|
||||||
@@ -66,7 +65,7 @@ enum ConnectionStatus {
|
|||||||
|
|
||||||
export function devicePlugin(client: DevicePluginClient) {
|
export function devicePlugin(client: DevicePluginClient) {
|
||||||
const metroDevice: MetroDevice = client.device.realDevice;
|
const metroDevice: MetroDevice = client.device.realDevice;
|
||||||
if (!metroDevice.sendCommand || !('ws' in metroDevice)) {
|
if (!metroDevice.sendMetroCommand) {
|
||||||
throw new Error('Invalid metroDevice');
|
throw new Error('Invalid metroDevice');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,12 +195,12 @@ export function devicePlugin(client: DevicePluginClient) {
|
|||||||
return;
|
return;
|
||||||
// Waiting for connection, but we do have an active Metro connection, lets force a reload to enter Dev Mode on app
|
// Waiting for connection, but we do have an active Metro connection, lets force a reload to enter Dev Mode on app
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
case connectionStatus.get() === ConnectionStatus.Initializing && !!metroDevice?.ws:
|
case connectionStatus.get() === ConnectionStatus.Initializing:
|
||||||
setStatus(
|
setStatus(
|
||||||
ConnectionStatus.WaitingForReload,
|
ConnectionStatus.WaitingForReload,
|
||||||
"Sending 'reload' to Metro to force the DevTools to connect...",
|
"Sending 'reload' to Metro to force the DevTools to connect...",
|
||||||
);
|
);
|
||||||
metroDevice!.sendCommand('reload');
|
metroDevice!.sendMetroCommand('reload');
|
||||||
startPollForConnection(2000);
|
startPollForConnection(2000);
|
||||||
return;
|
return;
|
||||||
// Waiting for initial connection, but no WS bridge available
|
// Waiting for initial connection, but no WS bridge available
|
||||||
@@ -295,12 +294,12 @@ export function Component() {
|
|||||||
<Typography.Text type="secondary">{statusMessage}</Typography.Text>
|
<Typography.Text type="secondary">{statusMessage}</Typography.Text>
|
||||||
) : null}
|
) : null}
|
||||||
{(connectionStatus === ConnectionStatus.WaitingForReload &&
|
{(connectionStatus === ConnectionStatus.WaitingForReload &&
|
||||||
instance.metroDevice?.ws) ||
|
instance.metroDevice) ||
|
||||||
connectionStatus === ConnectionStatus.Error ? (
|
connectionStatus === ConnectionStatus.Error ? (
|
||||||
<Button
|
<Button
|
||||||
size="small"
|
size="small"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
instance.metroDevice?.sendCommand('reload');
|
instance.metroDevice?.sendMetroCommand('reload');
|
||||||
instance.bootDevTools();
|
instance.bootDevTools();
|
||||||
}}>
|
}}>
|
||||||
Retry
|
Retry
|
||||||
|
|||||||
Reference in New Issue
Block a user