Support React Native buttons

Summary: Added the Metro buttons to AppInspect

Reviewed By: cekkaewnumchai

Differential Revision: D24544760

fbshipit-source-id: 1eb6face14a7950d654c95b1a8fca31b8efed99b
This commit is contained in:
Michel Weststrate
2020-10-27 05:16:10 -07:00
committed by Facebook GitHub Bot
parent 82604020ab
commit b8f68a4026
4 changed files with 45 additions and 28 deletions

View File

@@ -9,10 +9,11 @@
import React, {useCallback, useEffect, useState} from 'react'; import React, {useCallback, useEffect, useState} from 'react';
import {Button, ButtonGroup, colors} from '../ui'; import {Button, ButtonGroup, colors} from '../ui';
import {State} from '../reducers';
import MetroDevice, {MetroReportableEvent} from '../devices/MetroDevice'; import MetroDevice, {MetroReportableEvent} from '../devices/MetroDevice';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import {connect} from 'react-redux'; import {useStore} from '../utils/useStore';
import {Button as AntButton} from 'antd';
import {MenuOutlined, ReloadOutlined} from '@ant-design/icons';
type LogEntry = {}; type LogEntry = {};
@@ -20,10 +21,6 @@ export type PersistedState = {
logs: LogEntry[]; logs: LogEntry[];
}; };
type Props = {
device: MetroDevice;
};
function ProgressBar({ function ProgressBar({
progress, progress,
width, width,
@@ -57,10 +54,16 @@ const ProgressBarBar = styled.div<{progress: number; color: string}>(
}), }),
); );
function MetroButton({device}: Props) { export default function MetroButton({useSandy}: {useSandy?: boolean}) {
const device = useStore((state) =>
state.connections.devices.find(
(device) => device.os === 'Metro' && !device.isArchived,
),
) as MetroDevice | undefined;
const sendCommand = useCallback( const sendCommand = useCallback(
(command: string) => { (command: string) => {
device.sendCommand(command); device?.sendCommand(command);
}, },
[device], [device],
); );
@@ -68,6 +71,9 @@ function MetroButton({device}: Props) {
const [hasBuildError, setHasBuildError] = useState(false); const [hasBuildError, setHasBuildError] = useState(false);
useEffect(() => { useEffect(() => {
if (!device) {
return;
}
function metroEventListener(event: MetroReportableEvent) { function metroEventListener(event: MetroReportableEvent) {
if (event.type === 'bundle_build_started') { if (event.type === 'bundle_build_started') {
setHasBuildError(false); setHasBuildError(false);
@@ -88,7 +94,31 @@ function MetroButton({device}: Props) {
}; };
}, [device]); }, [device]);
return ( if (!device) {
return null;
}
return useSandy ? (
<>
<AntButton
icon={<ReloadOutlined />}
title="Reload React Native App"
type="ghost"
onClick={() => {
sendCommand('reload');
}}
loading={progress < 1}
/>
<AntButton
icon={<MenuOutlined />}
title="Open the React Native Dev Menu on the device"
type="ghost"
onClick={() => {
sendCommand('devMenu');
}}
/>
</>
) : (
<ButtonGroup> <ButtonGroup>
<Button <Button
title="Reload React Native App" title="Reload React Native App"
@@ -116,9 +146,3 @@ function MetroButton({device}: Props) {
</ButtonGroup> </ButtonGroup>
); );
} }
export default connect<Props, {}, {}, State>(({connections: {devices}}) => ({
device: devices.find(
(device) => device.os === 'Metro' && !device.isArchived,
) as MetroDevice,
}))(MetroButton);

View File

@@ -73,9 +73,7 @@ export default function ScreenCaptureButtons({useSandy}: {useSandy?: boolean}) {
} else { } else {
selectedDevice selectedDevice
.stopScreenCapture() .stopScreenCapture()
.then((path) => { .then(openFile)
path && openFile(path);
})
.catch((e) => { .catch((e) => {
console.error('Failed to start recording', e); console.error('Failed to start recording', e);
message.error('Failed to start recording' + e); message.error('Failed to start recording' + e);

View File

@@ -85,7 +85,6 @@ type StateFromProps = {
launcherMsg: LauncherMsg; launcherMsg: LauncherMsg;
share: ShareType | null | undefined; share: ShareType | null | undefined;
navPluginIsActive: boolean; navPluginIsActive: boolean;
isMetroActive: boolean;
}; };
const VersionText = styled(Text)({ const VersionText = styled(Text)({
@@ -150,7 +149,7 @@ function statusMessageComponent(
type Props = OwnProps & DispatchFromProps & StateFromProps; type Props = OwnProps & DispatchFromProps & StateFromProps;
class TitleBar extends React.Component<Props, StateFromProps> { class TitleBar extends React.Component<Props, StateFromProps> {
render() { render() {
const {navPluginIsActive, share, isMetroActive} = this.props; const {navPluginIsActive, share} = this.props;
return ( return (
<AppTitleBar focused={this.props.windowIsFocused} className="toolbar"> <AppTitleBar focused={this.props.windowIsFocused} className="toolbar">
{navPluginIsActive ? ( {navPluginIsActive ? (
@@ -162,7 +161,7 @@ class TitleBar extends React.Component<Props, StateFromProps> {
<DevicesButton /> <DevicesButton />
)} )}
{isMetroActive ? <MetroButton /> : null} <MetroButton />
<ScreenCaptureButtons /> <ScreenCaptureButtons />
{statusMessageComponent( {statusMessageComponent(
@@ -239,7 +238,7 @@ export default connect<StateFromProps, DispatchFromProps, OwnProps, State>(
launcherMsg, launcherMsg,
share, share,
}, },
connections: {selectedDevice, selectedApp, devices}, connections: {selectedDevice, selectedApp},
pluginStates, pluginStates,
}) => { }) => {
const navigationPluginKey = getPluginKey( const navigationPluginKey = getPluginKey(
@@ -248,9 +247,6 @@ export default connect<StateFromProps, DispatchFromProps, OwnProps, State>(
'Navigation', 'Navigation',
); );
const navPluginIsActive = !!pluginStates[navigationPluginKey]; const navPluginIsActive = !!pluginStates[navigationPluginKey];
const isMetroActive = !!devices.find(
(device) => device.os === 'Metro' && !device.isArchived,
);
return { return {
windowIsFocused, windowIsFocused,
@@ -261,7 +257,6 @@ export default connect<StateFromProps, DispatchFromProps, OwnProps, State>(
launcherMsg, launcherMsg,
share, share,
navPluginIsActive, navPluginIsActive,
isMetroActive,
}; };
}, },
{ {

View File

@@ -19,6 +19,7 @@ import {AppSelector} from './AppSelector';
import {useStore} from '../../utils/useStore'; import {useStore} from '../../utils/useStore';
import {PluginList} from './PluginList'; import {PluginList} from './PluginList';
import ScreenCaptureButtons from '../../chrome/ScreenCaptureButtons'; import ScreenCaptureButtons from '../../chrome/ScreenCaptureButtons';
import MetroButton from '../../chrome/MetroButton';
const appTooltip = ( const appTooltip = (
<> <>
@@ -46,8 +47,6 @@ export function AppInspect() {
<AppSelector /> <AppSelector />
<Input addonAfter={<SettingOutlined />} defaultValue="mysite" /> <Input addonAfter={<SettingOutlined />} defaultValue="mysite" />
<Toolbar gap> <Toolbar gap>
<Button icon={<SettingOutlined />} type="ghost" />
<Button icon={<SettingOutlined />} type="ghost" />
<Button <Button
icon={<RocketOutlined />} icon={<RocketOutlined />}
type="ghost" type="ghost"
@@ -56,6 +55,7 @@ export function AppInspect() {
showEmulatorLauncher(store); showEmulatorLauncher(store);
}} }}
/> />
<MetroButton useSandy />
<ScreenCaptureButtons useSandy /> <ScreenCaptureButtons useSandy />
</Toolbar> </Toolbar>
</Layout.Container> </Layout.Container>