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:
committed by
Facebook Github Bot
parent
51139500f4
commit
f30ff068a7
@@ -8,8 +8,7 @@
|
||||
import type {FlipperPlugin, FlipperDevicePlugin} from './plugin.js';
|
||||
import {
|
||||
exportStoreToFile,
|
||||
importFileToStore,
|
||||
IMPORT_FLIPPER_TRACE_EVENT,
|
||||
showOpenDialog,
|
||||
EXPORT_FLIPPER_TRACE_EVENT,
|
||||
} from './utils/exportData.js';
|
||||
import {setActiveSheet, ACTIVE_SHEET_SHARE_DATA} from './reducers/application';
|
||||
@@ -20,10 +19,7 @@ import {remote} from 'electron';
|
||||
const {dialog} = remote;
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
import {
|
||||
reportPlatformFailures,
|
||||
tryCatchReportPlatformFailures,
|
||||
} from './utils/metrics';
|
||||
import {reportPlatformFailures} from './utils/metrics';
|
||||
export type DefaultKeyboardAction = 'clear' | 'goToBottom' | 'createPaste';
|
||||
export type TopLevelMenu = 'Edit' | 'View' | 'Window' | 'Help';
|
||||
|
||||
@@ -329,18 +325,7 @@ function getTemplate(
|
||||
label: 'Open File...',
|
||||
accelerator: 'CommandOrControl+O',
|
||||
click: function(item: Object, focusedWindow: Object) {
|
||||
dialog.showOpenDialog(
|
||||
{
|
||||
properties: ['openFile'],
|
||||
},
|
||||
(files: Array<string>) => {
|
||||
if (files !== undefined && files.length > 0) {
|
||||
tryCatchReportPlatformFailures(() => {
|
||||
importFileToStore(files[0], store);
|
||||
}, `${IMPORT_FLIPPER_TRACE_EVENT}:UI`);
|
||||
}
|
||||
},
|
||||
);
|
||||
showOpenDialog(store);
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -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(
|
||||
// Physical devices
|
||||
const connectedDevices = [
|
||||
{
|
||||
label: 'Running devices',
|
||||
label: 'Connected 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 {
|
||||
...devices
|
||||
.filter(device => device.deviceType === 'physical')
|
||||
.map((device: BaseDevice) => ({
|
||||
click: () => selectDevice(device),
|
||||
checked: device === selectedDevice,
|
||||
label: `${label}${device.title}`,
|
||||
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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ import uuid from 'uuid';
|
||||
import {remote} from 'electron';
|
||||
import {serialize, deserialize} from './serialization';
|
||||
import {readCurrentRevision} from './packageMetadata.js';
|
||||
import {tryCatchReportPlatformFailures} from './metrics';
|
||||
|
||||
export const IMPORT_FLIPPER_TRACE_EVENT = 'import-flipper-trace';
|
||||
export const EXPORT_FLIPPER_TRACE_EVENT = 'export-flipper-trace';
|
||||
|
||||
@@ -337,3 +339,18 @@ export const importFileToStore = (file: string, store: Store) => {
|
||||
importDataToStore(data, store);
|
||||
});
|
||||
};
|
||||
|
||||
export function showOpenDialog(store: Store) {
|
||||
remote.dialog.showOpenDialog(
|
||||
{
|
||||
properties: ['openFile'],
|
||||
},
|
||||
(files: Array<string>) => {
|
||||
if (files !== undefined && files.length > 0) {
|
||||
tryCatchReportPlatformFailures(() => {
|
||||
importFileToStore(files[0], store);
|
||||
}, `${IMPORT_FLIPPER_TRACE_EVENT}:UI`);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -35,6 +35,14 @@ export const precachedIcons: Array<string> = [
|
||||
name: 'mobile',
|
||||
size: 12,
|
||||
},
|
||||
{
|
||||
name: 'box',
|
||||
size: 12,
|
||||
},
|
||||
{
|
||||
name: 'desktop',
|
||||
size: 12,
|
||||
},
|
||||
{
|
||||
name: 'bug',
|
||||
size: 12,
|
||||
|
||||
Reference in New Issue
Block a user