archive disconnected Android devices
Summary: Adding a `archive` method to Android devices, that returns a new ArchivedDevice with the same properties as the Android device. This method is called when an android device disconnects and the new ArchivedDevice is added to the devices list. When the device reconnects again, the archived device is removed. Currently only logs are persisted. In following diffs we can: - add support for iOS - move the persisted pluginStates to the archived device as well Reviewed By: passy Differential Revision: D15942904 fbshipit-source-id: 07c5415994594abd630d0c4b458b76d1aac6ef02
This commit is contained in:
committed by
Facebook Github Bot
parent
fdd75a123f
commit
74d7359cbe
@@ -6,7 +6,6 @@
|
||||
*/
|
||||
|
||||
import {Component, Button, styled} from 'flipper';
|
||||
import ArchivedDevice from '../devices/ArchivedDevice.js';
|
||||
import {connect} from 'react-redux';
|
||||
import {spawn} from 'child_process';
|
||||
import {dirname} from 'path';
|
||||
@@ -65,7 +64,7 @@ class DevicesButton extends Component<Props> {
|
||||
let buttonLabel = 'No device selected';
|
||||
let icon = 'minus-circle';
|
||||
|
||||
if (selectedDevice instanceof ArchivedDevice) {
|
||||
if (selectedDevice?.isArchived) {
|
||||
buttonLabel = `${selectedDevice?.title || 'Unknown device'} (offline)`;
|
||||
icon = 'box';
|
||||
} else if (selectedDevice?.deviceType === 'physical') {
|
||||
@@ -117,11 +116,11 @@ class DevicesButton extends Component<Props> {
|
||||
// Archived
|
||||
const importedFiles = [
|
||||
{
|
||||
label: 'Imported Devices',
|
||||
label: 'Disconnected Devices',
|
||||
enabled: false,
|
||||
},
|
||||
...devices
|
||||
.filter(device => device instanceof ArchivedDevice)
|
||||
.filter(device => device.isArchived)
|
||||
.map((device: BaseDevice) => ({
|
||||
click: () => selectDevice(device),
|
||||
checked: device === selectedDevice,
|
||||
@@ -137,8 +136,10 @@ class DevicesButton extends Component<Props> {
|
||||
const emulators = Array.from(androidEmulators)
|
||||
.filter(
|
||||
(name: string) =>
|
||||
devices.findIndex((device: BaseDevice) => device.title === name) ===
|
||||
-1,
|
||||
devices.findIndex(
|
||||
(device: BaseDevice) =>
|
||||
device.title === name && !device.isArchived,
|
||||
) === -1,
|
||||
)
|
||||
.map((name: string) => ({
|
||||
label: name,
|
||||
|
||||
@@ -11,6 +11,7 @@ import {Priority} from 'adbkit-logcat-fb';
|
||||
import child_process from 'child_process';
|
||||
import child_process_promise from 'child-process-es6-promise';
|
||||
import BaseDevice from './BaseDevice.js';
|
||||
import ArchivedDevice from './ArchivedDevice.js';
|
||||
|
||||
type ADBClient = any;
|
||||
|
||||
@@ -85,4 +86,14 @@ export default class AndroidDevice extends BaseDevice {
|
||||
clearLogs(): Promise<void> {
|
||||
return child_process_promise.spawn('adb', ['logcat', '-c']);
|
||||
}
|
||||
|
||||
archive(): ArchivedDevice {
|
||||
return new ArchivedDevice(
|
||||
this.serial,
|
||||
this.deviceType,
|
||||
this.title,
|
||||
this.os,
|
||||
[...this.logEntries],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,8 @@ export default class ArchivedDevice extends BaseDevice {
|
||||
|
||||
logs: Array<DeviceLogEntry>;
|
||||
|
||||
isArchived = true;
|
||||
|
||||
getLogs() {
|
||||
return this.logs;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
import type stream from 'stream';
|
||||
import type ArchivedDevice from './ArchivedDevice';
|
||||
|
||||
export type LogLevel =
|
||||
| 'unknown'
|
||||
@@ -74,6 +75,7 @@ export default class BaseDevice {
|
||||
|
||||
logListeners: Map<Symbol, DeviceLogListener> = new Map();
|
||||
logEntries: Array<DeviceLogEntry> = [];
|
||||
isArchived: boolean = false;
|
||||
|
||||
supportsOS(os: OS) {
|
||||
return os.toLowerCase() === this.os.toLowerCase();
|
||||
@@ -135,4 +137,8 @@ export default class BaseDevice {
|
||||
spawnShell(): ?DeviceShell {
|
||||
throw new Error('unimplemented');
|
||||
}
|
||||
|
||||
archive(): ?ArchivedDevice {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,6 +158,21 @@ export default (store: Store, logger: Logger) => {
|
||||
name: androidDevice.title,
|
||||
serial: androidDevice.serial,
|
||||
});
|
||||
|
||||
// remove offline devices with same serial as the connected.
|
||||
const reconnectedDevices = store
|
||||
.getState()
|
||||
.connections.devices.filter(
|
||||
(device: BaseDevice) =>
|
||||
device.serial === androidDevice.serial && device.isArchived,
|
||||
)
|
||||
.map(device => device.serial);
|
||||
|
||||
store.dispatch({
|
||||
type: 'UNREGISTER_DEVICES',
|
||||
payload: new Set(reconnectedDevices),
|
||||
});
|
||||
|
||||
store.dispatch({
|
||||
type: 'REGISTER_DEVICE',
|
||||
payload: androidDevice,
|
||||
@@ -178,10 +193,29 @@ export default (store: Store, logger: Logger) => {
|
||||
serial: id,
|
||||
}),
|
||||
);
|
||||
|
||||
const archivedDevices = deviceIds
|
||||
.map(id => {
|
||||
const device = store
|
||||
.getState()
|
||||
.connections.devices.find(device => device.serial === id);
|
||||
if (device && !device.isArchived) {
|
||||
return device.archive();
|
||||
}
|
||||
})
|
||||
.filter(Boolean);
|
||||
|
||||
store.dispatch({
|
||||
type: 'UNREGISTER_DEVICES',
|
||||
payload: new Set(deviceIds),
|
||||
});
|
||||
|
||||
archivedDevices.forEach((payload: BaseDevice) =>
|
||||
store.dispatch({
|
||||
type: 'REGISTER_DEVICE',
|
||||
payload,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
watchAndroidDevices();
|
||||
|
||||
Reference in New Issue
Block a user