Fix Flipper lints #16

Summary: Larger list of fixes. Adding another package to the flipper export is a bit nasty but it unblocks us for now and centralises `remote` access which seems like a win for FAAS.

Reviewed By: mweststrate

Differential Revision: D30785421

fbshipit-source-id: 931297e8566b5d8a213b69ae87d0cda7648b3ed4
This commit is contained in:
Pascal Hartig
2021-09-08 08:43:18 -07:00
committed by Facebook GitHub Bot
parent 262cd6105b
commit 47099cfd31
24 changed files with 293 additions and 201 deletions

View File

@@ -96,6 +96,7 @@ export {default as StatusIndicator} from './ui/components/StatusIndicator';
export {default as HorizontalRule} from './ui/components/HorizontalRule'; export {default as HorizontalRule} from './ui/components/HorizontalRule';
export {default as Label} from './ui/components/Label'; export {default as Label} from './ui/components/Label';
export {default as Heading} from './ui/components/Heading'; export {default as Heading} from './ui/components/Heading';
export * from './utils/pathUtils';
export {Filter} from './ui/components/filter/types'; export {Filter} from './ui/components/filter/types';
export {default as StackTrace} from './ui/components/StackTrace'; export {default as StackTrace} from './ui/components/StackTrace';
export { export {

View File

@@ -7,6 +7,9 @@
* @format * @format
*/ */
// We use sync access once per startup.
/* eslint-disable node/no-sync */
import path from 'path'; import path from 'path';
import fs from 'fs'; import fs from 'fs';
// In utils this is fine when used with caching. // In utils this is fine when used with caching.

View File

@@ -8,19 +8,20 @@
}, },
"devDependencies": { "devDependencies": {
"fs-extra": "^9.0.1", "fs-extra": "^9.0.1",
"p-map": "^4.0.0" "p-map": "^4.0.0",
"promisify-child-process": "^4.1.1"
}, },
"peerDependencies": { "peerDependencies": {
"flipper": "*",
"flipper-plugin": "*",
"antd": "*",
"react": "*",
"react-dom": "*",
"@emotion/styled": "*",
"@ant-design/icons": "*", "@ant-design/icons": "*",
"@emotion/styled": "*",
"@types/node": "*",
"@types/react": "*", "@types/react": "*",
"@types/react-dom": "*", "@types/react-dom": "*",
"@types/node": "*" "antd": "*",
"flipper": "*",
"flipper-plugin": "*",
"react": "*",
"react-dom": "*"
}, },
"scripts": { "scripts": {
"postinstall": "../ts-node ./postinstall.ts" "postinstall": "../ts-node ./postinstall.ts"

View File

@@ -7,7 +7,9 @@
* @format * @format
*/ */
import {execSync} from 'child_process'; /* eslint-disable flipper/no-console-error-without-context */
import {exec} from 'promisify-child-process';
import path from 'path'; import path from 'path';
import fs from 'fs-extra'; import fs from 'fs-extra';
import pmap from 'p-map'; import pmap from 'p-map';
@@ -90,14 +92,12 @@ async function postinstall(): Promise<number> {
} }
return 1; return 1;
} }
execSync('yarn install --mutex network:30330', { await exec('yarn install --mutex network:30330', {
cwd: publicPluginsDir, cwd: publicPluginsDir,
stdio: 'inherit',
}); });
if (await fs.pathExists(fbPluginsDir)) { if (await fs.pathExists(fbPluginsDir)) {
execSync('yarn install --mutex network:30330', { await exec('yarn install --mutex network:30330', {
cwd: fbPluginsDir, cwd: fbPluginsDir,
stdio: 'inherit',
}); });
} }
const peerDependenciesArray = Object.keys(peerDependencies); const peerDependenciesArray = Object.keys(peerDependencies);

View File

@@ -265,11 +265,15 @@ export function devicePlugin(client: PluginClient<{}, {}>) {
}); });
for (let i = 0; i < cpuState.get().cpuCount; ++i) { for (let i = 0; i < cpuState.get().cpuCount; ++i) {
readAvailableGovernors(i).then((output) => { readAvailableGovernors(i)
cpuState.update((draft) => { .then((output) => {
draft.cpuFreq[i].scaling_available_governors = output; cpuState.update((draft) => {
draft.cpuFreq[i].scaling_available_governors = output;
});
})
.catch((e) => {
console.error('Failed to read CPU governors:', e);
}); });
});
} }
const update = async () => { const update = async () => {
@@ -330,34 +334,38 @@ export function devicePlugin(client: PluginClient<{}, {}>) {
}; };
// check how many cores we have on this device // check how many cores we have on this device
executeShell('cat /sys/devices/system/cpu/possible').then((output) => { executeShell('cat /sys/devices/system/cpu/possible')
const idx = output.indexOf('-'); .then((output) => {
const cpuFreq = []; const idx = output.indexOf('-');
const count = parseInt(output.substring(idx + 1), 10) + 1; const cpuFreq = [];
for (let i = 0; i < count; ++i) { const count = parseInt(output.substring(idx + 1), 10) + 1;
cpuFreq[i] = { for (let i = 0; i < count; ++i) {
cpu_id: i, cpuFreq[i] = {
scaling_cur_freq: -1, cpu_id: i,
scaling_min_freq: -1, scaling_cur_freq: -1,
scaling_max_freq: -1, scaling_min_freq: -1,
cpuinfo_min_freq: -1, scaling_max_freq: -1,
cpuinfo_max_freq: -1, cpuinfo_min_freq: -1,
scaling_available_freqs: [], cpuinfo_max_freq: -1,
scaling_governor: 'N/A', scaling_available_freqs: [],
scaling_available_governors: [], scaling_governor: 'N/A',
}; scaling_available_governors: [],
} };
cpuState.set({ }
cpuCount: count, cpuState.set({
cpuFreq: cpuFreq, cpuCount: count,
monitoring: false, cpuFreq: cpuFreq,
hardwareInfo: '', monitoring: false,
temperatureMap: {}, hardwareInfo: '',
thermalAccessible: true, temperatureMap: {},
displayThermalInfo: false, thermalAccessible: true,
displayCPUDetail: true, displayThermalInfo: false,
displayCPUDetail: true,
});
})
.catch((e) => {
console.error('Failed to read CPU cores:', e);
}); });
});
client.onDeactivate(() => cleanup()); client.onDeactivate(() => cleanup());
client.onActivate(() => { client.onActivate(() => {

View File

@@ -24,5 +24,8 @@
"icon": "underline", "icon": "underline",
"bugs": { "bugs": {
"url": "https://github.com/facebook/flipper/issues" "url": "https://github.com/facebook/flipper/issues"
},
"dependencies": {
"fs-extra": "^10.0.0"
} }
} }

View File

@@ -30,7 +30,7 @@ export type CrashLog = {
export function devicePlugin(client: DevicePluginClient) { export function devicePlugin(client: DevicePluginClient) {
let notificationID = -1; let notificationID = -1;
let watcher: FSWatcher | undefined; let watcher: Promise<FSWatcher | undefined>;
const crashes = createState<Crash[]>([], {persist: 'crashes'}); const crashes = createState<Crash[]>([], {persist: 'crashes'});
const selectedCrash = createState<string | undefined>(); const selectedCrash = createState<string | undefined>();
@@ -70,7 +70,14 @@ export function devicePlugin(client: DevicePluginClient) {
} }
client.onDestroy(() => { client.onDestroy(() => {
watcher?.close(); watcher
.then((watcher) => watcher?.close())
.catch((e) =>
console.error(
'[crash_reporter] FSWatcher failed resoving on destroy:',
e,
),
);
}); });
return { return {

View File

@@ -8,10 +8,9 @@
*/ */
import type {CrashLog} from './index'; import type {CrashLog} from './index';
import fs from 'fs'; import fs from 'fs-extra';
import os from 'os'; import os from 'os';
import path from 'path'; import path from 'path';
import {promisify} from 'util';
import {UNKNOWN_CRASH_REASON} from './crash-utils'; import {UNKNOWN_CRASH_REASON} from './crash-utils';
export function parseIosCrash(content: string) { export function parseIosCrash(content: string) {
@@ -64,35 +63,34 @@ export function parsePath(content: string): string | null {
return path.trim(); return path.trim();
} }
export function addFileWatcherForiOSCrashLogs( export async function addFileWatcherForiOSCrashLogs(
serial: string, serial: string,
reportCrash: (payload: CrashLog) => void, reportCrash: (payload: CrashLog) => void,
) { ) {
const dir = path.join(os.homedir(), 'Library', 'Logs', 'DiagnosticReports'); const dir = path.join(os.homedir(), 'Library', 'Logs', 'DiagnosticReports');
if (!fs.existsSync(dir)) { if (!(await fs.pathExists(dir))) {
// Directory doesn't exist // Directory doesn't exist
return; return;
} }
return fs.watch(dir, (_eventType, filename) => { return fs.watch(dir, async (_eventType, filename) => {
// We just parse the crash logs with extension `.crash` // We just parse the crash logs with extension `.crash`
const checkFileExtension = /.crash$/.exec(filename); const checkFileExtension = /.crash$/.exec(filename);
if (!filename || !checkFileExtension) { if (!filename || !checkFileExtension) {
return; return;
} }
const filepath = path.join(dir, filename); const filepath = path.join(dir, filename);
promisify(fs.exists)(filepath).then((exists) => { const exists = await fs.pathExists(filepath);
if (!exists) { if (!exists) {
return;
}
fs.readFile(filepath, 'utf8', function (err, data) {
if (err) {
console.warn('Failed to read crash file', err);
return; return;
} }
fs.readFile(filepath, 'utf8', function (err, data) { if (shouldShowiOSCrashNotification(serial, data)) {
if (err) { reportCrash(parseIosCrash(data));
console.warn('Failed to read crash file', err); }
return;
}
if (shouldShowiOSCrashNotification(serial, data)) {
reportCrash(parseIosCrash(data));
}
});
}); });
}); });
} }

View File

@@ -32,6 +32,8 @@
"url": "https://fb.workplace.com/groups/220760072184928/" "url": "https://fb.workplace.com/groups/220760072184928/"
}, },
"dependencies": { "dependencies": {
"@types/fs-extra": "^9.0.12",
"fs-extra": "^10.0.0",
"unicode-substring": "^1.0.0" "unicode-substring": "^1.0.0"
}, },
"peerDependencies": { "peerDependencies": {

View File

@@ -39,15 +39,6 @@ type DatabaseDetailSidebarProps = {
onSave?: ((changes: {[key: string]: string | null}) => void) | undefined; onSave?: ((changes: {[key: string]: string | null}) => void) | undefined;
}; };
const EditTriggerSection = styled.div({
display: 'flex',
justifyContent: 'flex-end',
width: '100%',
paddingTop: '3px',
paddingBottom: '3px',
paddingRight: '10px',
});
const TableDetailRow = styled.div({ const TableDetailRow = styled.div({
borderBottom: `1px solid ${theme.dividerColor}`, borderBottom: `1px solid ${theme.dividerColor}`,
padding: 8, padding: 8,

View File

@@ -468,21 +468,27 @@ export function plugin(client: PluginClient<Events, Methods>) {
!previousState.outdatedDatabaseList && !previousState.outdatedDatabaseList &&
newState.outdatedDatabaseList newState.outdatedDatabaseList
) { ) {
client.send('databaseList', {}).then((databases) => { client
updateDatabases({ .send('databaseList', {})
databases, .then((databases) => {
}); updateDatabases({
}); databases,
});
})
.catch((e) => console.error('databaseList request failed:', e));
} }
}, },
); );
client.onConnect(() => { client.onConnect(() => {
client.send('databaseList', {}).then((databases) => { client
updateDatabases({ .send('databaseList', {})
databases, .then((databases) => {
}); updateDatabases({
}); databases,
});
})
.catch((e) => console.error('initial databaseList request failed:', e));
const loadedFavoritesJson = localStorage.getItem( const loadedFavoritesJson = localStorage.getItem(
FAVORITES_LOCAL_STORAGE_KEY, FAVORITES_LOCAL_STORAGE_KEY,
); );

View File

@@ -162,7 +162,7 @@ export function plugin(client: PluginClient<Events, Methods>) {
}); });
imageDataList.push(imageData); imageDataList.push(imageData);
} catch (e) { } catch (e) {
console.error(e); console.error('[fresco] getImage failed:', e);
} }
} }
@@ -232,10 +232,13 @@ export function plugin(client: PluginClient<Events, Methods>) {
return; return;
} }
debugLog('<- getImage requested for ' + imageId); debugLog('<- getImage requested for ' + imageId);
client.send('getImage', {imageId}).then((image: ImageData) => { client
debugLog('-> getImage ' + imageId + ' returned'); .send('getImage', {imageId})
imagePool.get()?._fetchCompleted(image); .then((image: ImageData) => {
}); debugLog('-> getImage ' + imageId + ' returned');
imagePool.get()?._fetchCompleted(image);
})
.catch((e) => console.error('[fresco] getImage failed:', e));
} }
function onImageSelected(selectedImage: ImageId) { function onImageSelected(selectedImage: ImageId) {
@@ -357,7 +360,8 @@ export function plugin(client: PluginClient<Events, Methods>) {
selectedSurfaces.get(), selectedSurfaces.get(),
coldStartFilter.get(), coldStartFilter.get(),
); );
}); })
.catch((e) => console.error('[fresco] listImages failed:', e));
} }
return { return {

View File

@@ -92,50 +92,48 @@ export default class extends FlipperDevicePlugin<State, any, any> {
checkDebugTargets = () => { checkDebugTargets = () => {
fetch(`${METRO_URL.toString()}json`) fetch(`${METRO_URL.toString()}json`)
.then((res) => res.json()) .then((res) => res.json())
.then( .then((result) => {
(result) => { // We only want to use the Chrome Reload targets.
// We only want to use the Chrome Reload targets. const targets = result.filter(
const targets = result.filter( (target: any) =>
(target: any) => target.title ===
target.title === 'React Native Experimental (Improved Chrome Reloads)',
'React Native Experimental (Improved Chrome Reloads)', );
);
// Find the currently selected target. // Find the currently selected target.
// If the current selectedTarget isn't returned, clear it. // If the current selectedTarget isn't returned, clear it.
let currentlySelected = null; let currentlySelected = null;
if (this.state.selectedTarget != null) { if (this.state.selectedTarget != null) {
for (const target of result) { for (const target of result) {
if ( if (
this.state.selectedTarget?.webSocketDebuggerUrl === this.state.selectedTarget?.webSocketDebuggerUrl ===
target.webSocketDebuggerUrl target.webSocketDebuggerUrl
) { ) {
currentlySelected = this.state.selectedTarget; currentlySelected = this.state.selectedTarget;
}
} }
} }
}
// Auto-select the first target if there is one, // Auto-select the first target if there is one,
// but don't change the one that's already selected. // but don't change the one that's already selected.
const selectedTarget = const selectedTarget =
currentlySelected == null && targets.length === 1 currentlySelected == null && targets.length === 1
? targets[0] ? targets[0]
: currentlySelected; : currentlySelected;
this.setState({ this.setState({
error: null, error: null,
targets, targets,
selectedTarget, selectedTarget,
}); });
}, })
(error) => { .catch((error) => {
this.setState({ this.setState({
targets: null, targets: null,
selectedTarget: null, selectedTarget: null,
error, error,
}); });
}, });
);
}; };
handleSelect = (selectedTarget: Target) => this.setState({selectedTarget}); handleSelect = (selectedTarget: Target) => this.setState({selectedTarget});

View File

@@ -119,13 +119,16 @@ export default class Inspector extends Component<Props, State> {
if (!this.props.client.isConnected) { if (!this.props.client.isConnected) {
return; return;
} }
this.props.client.call(this.call().GET_ROOT).then((root: Element) => { this.props.client
this.props.setPersistedState({ .call(this.call().GET_ROOT)
[this.props.ax ? 'rootAXElement' : 'rootElement']: root.id, .then((root: Element) => {
}); this.props.setPersistedState({
this.updateElement(root.id, {...root, expanded: true}); [this.props.ax ? 'rootAXElement' : 'rootElement']: root.id,
this.performInitialExpand(root); });
}); this.updateElement(root.id, {...root, expanded: true});
this.performInitialExpand(root);
})
.catch((e) => console.error('[layout] GET_ROOT failed:', e));
this.props.client.subscribe( this.props.client.subscribe(
this.call().INVALIDATE, this.call().INVALIDATE,
@@ -419,13 +422,15 @@ export default class Inspector extends Component<Props, State> {
if (shouldExpand) { if (shouldExpand) {
this.updateElement(id, {expanded: shouldExpand}); this.updateElement(id, {expanded: shouldExpand});
} }
this.getChildren(id, {}).then((children) => { this.getChildren(id, {})
if (deep) { .then((children) => {
children.forEach((child) => if (deep) {
this.onElementExpanded(child.id, deep, shouldExpand), children.forEach((child) =>
); this.onElementExpanded(child.id, deep, shouldExpand),
} );
}); }
})
.catch((e) => console.error('[layout] getChildren failed:', e));
if (!shouldExpand) { if (!shouldExpand) {
this.updateElement(id, {expanded: shouldExpand}); this.updateElement(id, {expanded: shouldExpand});
} }

View File

@@ -101,7 +101,8 @@ export default class Search extends Component<Props, State> {
.call('getSearchResults', {query, axEnabled: this.props.inAXMode}) .call('getSearchResults', {query, axEnabled: this.props.inAXMode})
.then((response) => .then((response) =>
this.displaySearchResults(response, this.props.inAXMode), this.displaySearchResults(response, this.props.inAXMode),
); )
.catch((e) => console.log('[layout] getSearchResults failed:', e));
} }
} }

View File

@@ -218,9 +218,12 @@ export default class LayoutPlugin extends FlipperPlugin<
if (this.client.isConnected) { if (this.client.isConnected) {
// persist searchActive state when moving between plugins to prevent multiple // persist searchActive state when moving between plugins to prevent multiple
// TouchOverlayViews since we can't edit the view heirarchy in onDisconnect // TouchOverlayViews since we can't edit the view heirarchy in onDisconnect
this.client.call('isSearchActive').then(({isSearchActive}) => { this.client
this.setState({inTargetMode: isSearchActive}); .call('isSearchActive')
}); .then(({isSearchActive}) => {
this.setState({inTargetMode: isSearchActive});
})
.catch((e) => console.error('[layout] isSearchActive call failed:', e));
// disable target mode after // disable target mode after
this.client.subscribe('select', () => { this.client.subscribe('select', () => {

View File

@@ -94,9 +94,11 @@ export function plugin(client: PluginClient<Events, Methods>) {
console.error('[Navigation] Failed to find appMatchPatterns', e); console.error('[Navigation] Failed to find appMatchPatterns', e);
}); });
readBookmarksFromDB().then((bookmarksData) => { readBookmarksFromDB()
bookmarks.set(bookmarksData); .then((bookmarksData) => {
}); bookmarks.set(bookmarksData);
})
.catch((e) => console.error('[navigation] readBookmarksFromDB failed:', e));
function navigateTo(query: string) { function navigateTo(query: string) {
const filteredQuery = filterOptionalParameters(query); const filteredQuery = filterOptionalParameters(query);

View File

@@ -9,15 +9,13 @@
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
import {BaseDevice, AndroidDevice, IOSDevice} from 'flipper'; import {BaseDevice, AndroidDevice, IOSDevice, getAppPath} from 'flipper';
import {AppMatchPattern} from '../types'; import {AppMatchPattern} from '../types';
import {remote} from 'electron';
let patternsPath: string | undefined; let patternsPath: string | undefined;
function getPatternsBasePath() { function getPatternsBasePath() {
return (patternsPath = return (patternsPath = patternsPath ?? path.join(getAppPath(), 'facebook'));
patternsPath ?? path.join(remote.app.getAppPath(), 'facebook'));
} }
const extractAppNameFromSelectedApp = (selectedApp: string | null) => { const extractAppNameFromSelectedApp = (selectedApp: string | null) => {

View File

@@ -41,7 +41,9 @@ const openNavigationPluginDB: () => Promise<IDBDatabase> = () => {
); );
openRequest.onupgradeneeded = () => { openRequest.onupgradeneeded = () => {
const db = openRequest.result; const db = openRequest.result;
initializeNavigationPluginDB(db).then(() => resolve(db)); initializeNavigationPluginDB(db)
.then(() => resolve(db))
.catch(reject);
}; };
openRequest.onerror = () => reject(openRequest.error); openRequest.onerror = () => reject(openRequest.error);
openRequest.onsuccess = () => resolve(openRequest.result); openRequest.onsuccess = () => resolve(openRequest.result);

View File

@@ -236,20 +236,23 @@ export function plugin(client: PluginClient<Events, Methods>) {
} }
function init() { function init() {
supportsMocks(client.device).then((result) => { supportsMocks(client.device)
const newRoutes = JSON.parse( .then((result) => {
localStorage.getItem(LOCALSTORAGE_MOCK_ROUTE_LIST_KEY + client.appId) || const newRoutes = JSON.parse(
'{}', localStorage.getItem(
); LOCALSTORAGE_MOCK_ROUTE_LIST_KEY + client.appId,
batch(() => { ) || '{}',
routes.set(newRoutes); );
isMockResponseSupported.set(result); batch(() => {
showMockResponseDialog.set(false); routes.set(newRoutes);
nextRouteId.set(Object.keys(routes.get()).length); isMockResponseSupported.set(result);
}); showMockResponseDialog.set(false);
nextRouteId.set(Object.keys(routes.get()).length);
});
informClientMockChange(routes.get()); informClientMockChange(routes.get());
}); })
.catch((e) => console.error('[network] Failed to init mocks:', e));
// declare new variable to be called inside the interface // declare new variable to be called inside the interface
networkRouteManager.set( networkRouteManager.set(

View File

@@ -13,7 +13,6 @@ import electron, {OpenDialogOptions, remote} from 'electron';
import {Atom, DataTableManager} from 'flipper-plugin'; import {Atom, DataTableManager} from 'flipper-plugin';
import {createContext} from 'react'; import {createContext} from 'react';
import {Header, Request} from '../types'; import {Header, Request} from '../types';
import {bodyAsString, decodeBody} from '../utils';
import {message} from 'antd'; import {message} from 'antd';
export type Route = { export type Route = {
@@ -142,35 +141,40 @@ export function createNetworkManager(
properties: ['openFile'], properties: ['openFile'],
filters: [{extensions: ['json'], name: 'Flipper Route Files'}], filters: [{extensions: ['json'], name: 'Flipper Route Files'}],
}; };
remote.dialog.showOpenDialog(options).then((result) => { remote.dialog
const filePaths = result.filePaths; .showOpenDialog(options)
if (filePaths.length > 0) { .then((result) => {
fs.readFile(filePaths[0], 'utf8', (err, data) => { const filePaths = result.filePaths;
if (err) { if (filePaths.length > 0) {
message.error('Unable to import file'); fs.readFile(filePaths[0], 'utf8', (err, data) => {
return; if (err) {
} message.error('Unable to import file');
const importedRoutes = JSON.parse(data); return;
importedRoutes?.forEach((importedRoute: Route) => {
if (importedRoute != null) {
const newNextRouteId = nextRouteId.get();
routes.update((draft) => {
draft[newNextRouteId.toString()] = {
requestUrl: importedRoute.requestUrl,
requestMethod: importedRoute.requestMethod,
responseData: importedRoute.responseData as string,
responseHeaders: importedRoute.responseHeaders,
responseStatus: importedRoute.responseStatus,
enabled: true,
};
});
nextRouteId.set(newNextRouteId + 1);
} }
const importedRoutes = JSON.parse(data);
importedRoutes?.forEach((importedRoute: Route) => {
if (importedRoute != null) {
const newNextRouteId = nextRouteId.get();
routes.update((draft) => {
draft[newNextRouteId.toString()] = {
requestUrl: importedRoute.requestUrl,
requestMethod: importedRoute.requestMethod,
responseData: importedRoute.responseData as string,
responseHeaders: importedRoute.responseHeaders,
responseStatus: importedRoute.responseStatus,
enabled: true,
};
});
nextRouteId.set(newNextRouteId + 1);
}
});
informClientMockChange(routes.get());
}); });
informClientMockChange(routes.get()); }
}); })
} .catch((e) =>
}); console.error('[network] importRoutes dialogue failed:', e),
);
}, },
exportRoutes() { exportRoutes() {
remote.dialog remote.dialog
@@ -199,7 +203,10 @@ export function createNetworkManager(
} }
}, },
); );
}); })
.catch((e) =>
console.error('[network] exportRoutes saving failed:', e),
);
}, },
clearRoutes() { clearRoutes() {
routes.set({}); routes.set({});

View File

@@ -7,9 +7,14 @@
* @format * @format
*/ */
import {FlipperPlugin} from 'flipper'; import {
import {FlexColumn} from 'flipper'; FlipperPlugin,
import {ButtonGroup, Button, styled, colors} from 'flipper'; FlexColumn,
ButtonGroup,
Button,
styled,
colors,
} from 'flipper';
import React, {ChangeEvent} from 'react'; import React, {ChangeEvent} from 'react';
export type Sandbox = { export type Sandbox = {
@@ -75,9 +80,12 @@ export default class SandboxView extends FlipperPlugin<
if (!this.client.isConnected) { if (!this.client.isConnected) {
return; return;
} }
this.client.call('getSandbox', {}).then((results: Array<Sandbox>) => { this.client
this.setState({sandboxes: results}); .call('getSandbox', {})
}); .then((results: Array<Sandbox>) => {
this.setState({sandboxes: results});
})
.catch((e) => console.error('[sandbox] getSandbox call failed:', e));
} }
onSendSandboxEnvironment = (sandbox: string) => { onSendSandboxEnvironment = (sandbox: string) => {
@@ -90,7 +98,8 @@ export default class SandboxView extends FlipperPlugin<
this.setState({showFeedback: false}); this.setState({showFeedback: false});
}, 3000); }, 3000);
this.setState({showFeedback: result.result}); this.setState({showFeedback: result.result});
}); })
.catch((e) => console.error('[sandbox] setSandbox call failed:', e));
}; };
onChangeSandbox = (e: ChangeEvent<HTMLInputElement>) => { onChangeSandbox = (e: ChangeEvent<HTMLInputElement>) => {

View File

@@ -165,6 +165,13 @@
resolved "https://registry.yarnpkg.com/@types/dateformat/-/dateformat-3.0.1.tgz#98d747a2e5e9a56070c6bf14e27bff56204e34cc" resolved "https://registry.yarnpkg.com/@types/dateformat/-/dateformat-3.0.1.tgz#98d747a2e5e9a56070c6bf14e27bff56204e34cc"
integrity sha512-KlPPdikagvL6ELjWsljbyDIPzNCeliYkqRpI+zea99vBBbCIA5JNshZAwQKTON139c87y9qvTFVgkFd14rtS4g== integrity sha512-KlPPdikagvL6ELjWsljbyDIPzNCeliYkqRpI+zea99vBBbCIA5JNshZAwQKTON139c87y9qvTFVgkFd14rtS4g==
"@types/fs-extra@^9.0.12":
version "9.0.12"
resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-9.0.12.tgz#9b8f27973df8a7a3920e8461517ebf8a7d4fdfaf"
integrity sha512-I+bsBr67CurCGnSenZZ7v94gd3tc3+Aj2taxMT4yu4ABLuOgOjeFxX3dokG24ztSRg5tnT00sL8BszO7gSMoIw==
dependencies:
"@types/node" "*"
"@types/hoist-non-react-statics@^3.3.0": "@types/hoist-non-react-statics@^3.3.0":
version "3.3.1" version "3.3.1"
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f" resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
@@ -709,6 +716,15 @@ fragment-cache@^0.2.1:
dependencies: dependencies:
map-cache "^0.2.2" map-cache "^0.2.2"
fs-extra@^10.0.0:
version "10.0.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.0.0.tgz#9ff61b655dde53fb34a82df84bb214ce802e17c1"
integrity sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==
dependencies:
graceful-fs "^4.2.0"
jsonfile "^6.0.1"
universalify "^2.0.0"
fs-extra@^4.0.3: fs-extra@^4.0.3:
version "4.0.3" version "4.0.3"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94"
@@ -759,6 +775,11 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6:
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==
graceful-fs@^4.2.0:
version "4.2.8"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a"
integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==
has-flag@^3.0.0: has-flag@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
@@ -956,6 +977,15 @@ jsonfile@^4.0.0:
optionalDependencies: optionalDependencies:
graceful-fs "^4.1.6" graceful-fs "^4.1.6"
jsonfile@^6.0.1:
version "6.1.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae"
integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==
dependencies:
universalify "^2.0.0"
optionalDependencies:
graceful-fs "^4.1.6"
kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0:
version "3.2.2" version "3.2.2"
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
@@ -1611,6 +1641,11 @@ universalify@^0.1.0:
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
universalify@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717"
integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==
unset-value@^1.0.0: unset-value@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559"

View File

@@ -56,6 +56,11 @@ p-map@^4.0.0:
dependencies: dependencies:
aggregate-error "^3.0.0" aggregate-error "^3.0.0"
promisify-child-process@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/promisify-child-process/-/promisify-child-process-4.1.1.tgz#290659e079f9c7bd46708404d4488a1a6b802686"
integrity sha512-/sRjHZwoXf1rJ+8s4oWjYjGRVKNK1DUnqfRC1Zek18pl0cN6k3yJ1cCbqd0tWNe4h0Gr+SY4vR42N33+T82WkA==
universalify@^1.0.0: universalify@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-1.0.0.tgz#b61a1da173e8435b2fe3c67d29b9adf8594bd16d" resolved "https://registry.yarnpkg.com/universalify/-/universalify-1.0.0.tgz#b61a1da173e8435b2fe3c67d29b9adf8594bd16d"