Hide app selector if no devices are available

Summary:
As reported in https://fb.workplace.com/groups/748354712423318/permalink/773382183253904/, special case no devices being present and suggest to launch an emulator.

Also extends `useStore()` hook to accept no arguments, in which case it works as Redux's own `useStore` hook, except that it is strongly typed.

Reviewed By: passy

Differential Revision: D25803497

fbshipit-source-id: d448ac41e0ba7b713ee883caeb27736a2901975c
This commit is contained in:
Michel Weststrate
2021-01-06 08:23:06 -08:00
committed by Facebook GitHub Bot
parent dbf194b952
commit 30ea098a63
3 changed files with 51 additions and 13 deletions

View File

@@ -47,7 +47,6 @@ import {logout, USER_NOT_SIGNEDIN, USER_UNAUTHORIZED} from '../reducers/user';
import config from '../fb-stubs/config';
import styled from '@emotion/styled';
import {showEmulatorLauncher} from './appinspect/LaunchEmulator';
import {useStore as useReduxStore} from 'react-redux';
import SupportRequestFormV2 from '../fb-stubs/SupportRequestFormV2';
import {setStaticView} from '../reducers/connections';
import {getInstance} from '../fb-stubs/Logger';
@@ -252,7 +251,7 @@ function DebugLogsButton({
}
function LaunchEmulatorButton() {
const store = useReduxStore();
const store = useStore();
return (
<LeftRailButton

View File

@@ -8,12 +8,13 @@
*/
import React from 'react';
import {Button, Dropdown, Menu, Radio, Typography} from 'antd';
import {Alert, Button, Dropdown, Menu, Radio, Typography} from 'antd';
import {
AppleOutlined,
AndroidOutlined,
WindowsOutlined,
CaretDownOutlined,
RocketOutlined,
} from '@ant-design/icons';
import {Glyph, Layout, styled} from '../../ui';
import {theme, useTrackedCallback} from 'flipper-plugin';
@@ -30,8 +31,9 @@ import {getColorByApp} from '../../chrome/mainsidebar/sidebarUtils';
import Client from '../../Client';
import {State} from '../../reducers';
import {brandIcons} from '../../ui/components/colors';
import {showEmulatorLauncher} from './LaunchEmulator';
const {Text} = Typography;
const {Text, Link, Title} = Typography;
function getOsIcon(os?: OS) {
switch (os) {
@@ -86,7 +88,7 @@ export function AppSelector() {
);
const client = clients.find((client) => client.id === selectedApp);
return (
return entries.length ? (
<Radio.Group
value={selectedApp}
size="small"
@@ -96,9 +98,7 @@ export function AppSelector() {
}}>
<Dropdown
overlay={
<Menu selectedKeys={selectedApp ? [selectedApp] : []}>
{entries.flat()}
</Menu>
<Menu selectedKeys={selectedApp ? [selectedApp] : []}>{entries}</Menu>
}>
<AppInspectButton title="Select the device / app to inspect">
<Layout.Horizontal gap center>
@@ -114,6 +114,8 @@ export function AppSelector() {
</AppInspectButton>
</Dropdown>
</Radio.Group>
) : (
<NoDevices />
);
}
@@ -216,5 +218,36 @@ function computeEntries(
)),
]);
}
return entries;
return entries.flat();
}
function NoDevices() {
const store = useStore();
const onLaunchEmulator = useTrackedCallback(
'select-emulator',
() => {
showEmulatorLauncher(store);
},
[],
);
return (
<Alert
type="info"
message={
<>
<Title level={4}>No devices found</Title>
<Text>
Start a fresh emulator <RocketOutlined onClick={onLaunchEmulator} />{' '}
or check the{' '}
<Link href="https://fbflipper.com/docs/troubleshooting">
troubleshooting guide
</Link>
.
</Text>
</>
}
/>
);
}

View File

@@ -8,12 +8,13 @@
*/
import {
useStore as useReduxStore,
useSelector,
shallowEqual,
useDispatch as useDispatchBase,
} from 'react-redux';
import {Dispatch as ReduxDispatch} from 'redux';
import {State, Actions} from '../reducers/index';
import {State, Actions, Store} from '../reducers/index';
/**
* Strongly typed wrapper or Redux's useSelector.
@@ -22,9 +23,14 @@ import {State, Actions} from '../reducers/index';
*/
export function useStore<Selected>(
selector: (state: State) => Selected,
equalityFn: (left: Selected, right: Selected) => boolean = shallowEqual,
): Selected {
return useSelector(selector, equalityFn);
equalityFn?: (left: Selected, right: Selected) => boolean,
): Selected;
export function useStore(): Store;
export function useStore(selector?: any, equalityFn?: any) {
// eslint-disable-next-line react-hooks/rules-of-hooks
if (arguments.length === 0) return useReduxStore();
// eslint-disable-next-line react-hooks/rules-of-hooks
return useSelector(selector, equalityFn ?? shallowEqual);
}
export type Dispatch = ReduxDispatch<Actions>;