Show offline devices in dropdown

Summary:
This diff aims to make the selected device a little clearer, the button now shows different icons depending on the selected devices: physical, emulators and archived devices.

The dropdown now is grouped in these sections, depending on their availability:
- Connected Devices
- Running Emulators
- Imported Devices
- Launch Android emulators
- Open File...

"Open File..." allows to import a file the same way as File -> Open File...

Reviewed By: jknoxville

Differential Revision: D14460789

fbshipit-source-id: 8d6edff0d90d5e02e4ef5976af5680ab8eaf77b4
This commit is contained in:
Daniel Büchele
2019-03-15 11:27:30 -07:00
committed by Facebook Github Bot
parent 51139500f4
commit f30ff068a7
4 changed files with 108 additions and 54 deletions

View File

@@ -6,12 +6,15 @@
*/
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';
import {selectDevice, preferDevice} from '../reducers/connections.js';
import {default as which} from 'which';
import {promisify} from 'util';
import {showOpenDialog} from '../utils/exportData';
import PropTypes from 'prop-types';
import type BaseDevice from '../devices/BaseDevice.js';
const whichPromise = promisify(which);
@@ -29,6 +32,10 @@ const DropdownButton = styled(Button)({
});
class DevicesButton extends Component<Props> {
static contextTypes = {
store: PropTypes.object.isRequired,
};
launchEmulator = (name: string) => {
// On Linux, you must run the emulator from the directory it's in because
// reasons ...
@@ -54,49 +61,77 @@ class DevicesButton extends Component<Props> {
selectedDevice,
selectDevice,
} = this.props;
let text = 'No device selected';
let buttonLabel = 'No device selected';
let icon = 'minus-circle';
if (selectedDevice) {
text = selectedDevice.title;
if (selectedDevice instanceof ArchivedDevice) {
buttonLabel = `${selectedDevice?.title || 'Unknown device'} (offline)`;
icon = 'box';
} else if (selectedDevice?.deviceType === 'physical') {
buttonLabel = selectedDevice?.title || 'Unknown device';
icon = 'mobile';
} else if (selectedDevice?.deviceType === 'emulator') {
buttonLabel = selectedDevice?.title || 'Unknown emulator';
icon = 'desktop';
}
const dropdown = [];
if (devices.length > 0) {
dropdown.push(
{
label: 'Running devices',
enabled: false,
},
...devices.map((device: BaseDevice) => {
let label = '';
switch (device.deviceType) {
case 'emulator':
label = '';
break;
case 'physical':
label = '📱 ';
break;
case 'archivedEmulator':
label = '📦 ';
break;
case 'archivedPhysical':
label = '📦 ';
break;
default:
label = '';
}
return {
click: () => selectDevice(device),
checked: device === selectedDevice,
label: `${label}${device.title}`,
type: 'checkbox',
};
}),
);
// Physical devices
const connectedDevices = [
{
label: 'Connected Devices',
enabled: false,
},
...devices
.filter(device => device.deviceType === 'physical')
.map((device: BaseDevice) => ({
click: () => selectDevice(device),
checked: device === selectedDevice,
label: `📱 ${device.title}`,
type: 'checkbox',
})),
];
if (connectedDevices.length > 1) {
dropdown.push(...connectedDevices);
}
// Emulators
const runningEmulators = [
{
label: 'Running Emulators',
enabled: false,
},
...devices
.filter(device => device.deviceType === 'emulator')
.map((device: BaseDevice) => ({
click: () => selectDevice(device),
checked: device === selectedDevice,
label: device.title,
type: 'checkbox',
})),
];
if (runningEmulators.length > 1) {
dropdown.push(...runningEmulators);
}
// Archived
const importedFiles = [
{
label: 'Imported Devices',
enabled: false,
},
...devices
.filter(device => device instanceof ArchivedDevice)
.map((device: BaseDevice) => ({
click: () => selectDevice(device),
checked: device === selectedDevice,
label: `📦 ${device.title} (offline)`,
type: 'checkbox',
})),
];
if (importedFiles.length > 1) {
dropdown.push(...importedFiles);
}
// Launch Android emulators
if (androidEmulators.length > 0) {
const emulators = Array.from(androidEmulators)
.filter(
@@ -119,9 +154,18 @@ class DevicesButton extends Component<Props> {
);
}
}
if (dropdown.length > 0) {
dropdown.push({type: 'separator'});
}
dropdown.push({
label: 'Open File...',
click: () => {
showOpenDialog(this.context.store);
},
});
return (
<DropdownButton compact={true} icon={icon} dropdown={dropdown}>
{text}
{buttonLabel}
</DropdownButton>
);
}