Hide "no application selected" warning when there is no device

Summary:
In the left App Inspect sidebar on Flipper there were two warning messages
- "no devices found"
- "no application selected"

As there can be no application selected, while no device is active, this change removes the "no application selected" warning. Resulting in only showing one warning at a time.

As I am not familiar with all the states, nor what kind of devices or applications can exist in detail, I have moved up the logic to show the "no device found" message. Then reused it for the "no application selected" visibility.

In case the upper device list can show "connecting" without an actual device in the list, the "no application selected" message will be shown.

Reviewed By: passy

Differential Revision: D32139077

fbshipit-source-id: 06456e81fbe1f86d65f9aba598ee84ed8cd6b043
This commit is contained in:
Gerard Delmas
2021-11-04 05:12:35 -07:00
committed by Facebook GitHub Bot
parent 3ff955c42b
commit 6bcb5a435b
3 changed files with 59 additions and 48 deletions

View File

@@ -26,6 +26,7 @@ import {
getActiveDevice,
getMetroDevice,
} from '../../selectors/connections';
import * as connections from '../../selectors/connections';
const {Text} = Typography;
@@ -46,6 +47,7 @@ export function AppInspect() {
const activeDevice = useSelector(getActiveDevice);
const isDeviceConnected = useValue(activeDevice?.connected, false);
const isAppConnected = useValue(client?.connected, false);
const hasSelectableDevices = useSelector(connections.hasSelectableDevices);
return (
<LeftSidebar>
@@ -61,6 +63,7 @@ export function AppInspect() {
activeDevice,
client,
isAppConnected,
hasSelectableDevices,
)}
{isDeviceConnected && isAppConnected && <BookmarkSection />}
{isDeviceConnected && activeDevice && (
@@ -96,6 +99,7 @@ function renderStatusMessage(
activeDevice: BaseDevice | null,
client: Client | null,
isAppConnected: boolean,
hasSelectableDevices: boolean,
): React.ReactNode {
if (!activeDevice) {
return;
@@ -142,7 +146,7 @@ function renderStatusMessage(
</Text>
</Layout.Horizontal>
)
) : (
) : hasSelectableDevices ? (
<Layout.Horizontal gap center>
<ExclamationCircleOutlined style={{color: theme.warningColor}} />
<Text
@@ -155,5 +159,5 @@ function renderStatusMessage(
No application selected
</Text>
</Layout.Horizontal>
);
) : null /* no selectable devices */;
}

View File

@@ -18,10 +18,9 @@ import {
} from '@ant-design/icons';
import {Glyph, Layout, styled} from '../../ui';
import {DeviceOS, theme, useTrackedCallback, useValue} from 'flipper-plugin';
import {batch} from 'react-redux';
import {batch, useSelector} from 'react-redux';
import {useDispatch, useStore} from '../../utils/useStore';
import {
canBeDefaultDevice,
getClientsByDevice,
selectClient,
selectDevice,
@@ -32,6 +31,7 @@ import {State} from '../../reducers';
import {brandColors, brandIcons, colors} from '../../ui/components/colors';
import {TroubleshootingGuide} from './fb-stubs/TroubleshootingGuide';
import GK from '../../fb-stubs/GK';
import {getSelectableDevices} from '../../selectors/connections';
const {Text} = Typography;
@@ -50,13 +50,9 @@ function getOsIcon(os?: DeviceOS) {
export function AppSelector() {
const dispatch = useDispatch();
const {
devices,
selectedDevice,
clients,
uninitializedClients,
selectedAppId,
} = useStore((state) => state.connections);
const selectableDevices = useSelector(getSelectableDevices);
const {selectedDevice, clients, uninitializedClients, selectedAppId} =
useStore((state) => state.connections);
useValue(selectedDevice?.connected, false); // subscribe to future archived state changes
const onSelectDevice = useTrackedCallback(
@@ -79,7 +75,7 @@ export function AppSelector() {
);
const entries = computeEntries(
devices,
selectableDevices,
clients,
uninitializedClients,
onSelectDevice,
@@ -193,47 +189,37 @@ const AppIconContainer = styled.div({
});
function computeEntries(
devices: BaseDevice[],
selectableDevices: BaseDevice[],
clients: Map<string, Client>,
uninitializedClients: State['connections']['uninitializedClients'],
onSelectDevice: (device: BaseDevice) => void,
onSelectApp: (device: BaseDevice, client: Client) => void,
) {
const entries = devices
.filter(
(device) =>
// hide non default devices, unless they have a connected client or plugins
canBeDefaultDevice(device) ||
device.hasDevicePlugins ||
getClientsByDevice(device, clients).length > 0,
)
.map((device) => {
const deviceEntry = (
<Menu.Item
icon={getOsIcon(device.os)}
key={device.serial}
style={{fontWeight: 'bold'}}
onClick={() => {
onSelectDevice(device);
}}>
<DeviceTitle device={device} />
</Menu.Item>
);
const clientEntries = getClientsByDevice(device, clients).map(
(client) => (
<Menu.Item
key={client.id}
onClick={() => {
onSelectApp(device, client);
}}>
<Radio value={client.id}>
<ClientTitle client={client} />
</Radio>
</Menu.Item>
),
);
return [deviceEntry, ...clientEntries];
});
const entries = selectableDevices.map((device) => {
const deviceEntry = (
<Menu.Item
icon={getOsIcon(device.os)}
key={device.serial}
style={{fontWeight: 'bold'}}
onClick={() => {
onSelectDevice(device);
}}>
<DeviceTitle device={device} />
</Menu.Item>
);
const clientEntries = getClientsByDevice(device, clients).map((client) => (
<Menu.Item
key={client.id}
onClick={() => {
onSelectApp(device, client);
}}>
<Radio value={client.id}>
<ClientTitle client={client} />
</Radio>
</Menu.Item>
));
return [deviceEntry, ...clientEntries];
});
if (uninitializedClients.length) {
entries.push([
<Menu.Item key="connecting" style={{fontWeight: 'bold'}}>

View File

@@ -14,10 +14,12 @@ import {
computeActivePluginList,
} from '../utils/pluginUtils';
import createSelector from './createSelector';
import {canBeDefaultDevice, getClientsByDevice} from '../reducers/connections';
const getSelectedPluginId = (state: State) => state.connections.selectedPlugin;
const getSelectedDevice = (state: State) => state.connections.selectedDevice;
const getDevices = (state: State) => state.connections.devices;
const getClients = (state: State) => state.connections.clients;
const getPluginDownloads = (state: State) => state.pluginDownloads;
// N.B. no useSelector, It can't memoise on maps :-/
@@ -31,6 +33,25 @@ export const getMetroDevice = createSelector(getDevices, (devices) => {
);
});
export const getSelectableDevices = createSelector(
getDevices,
getClients,
(devices, clients) => {
return devices.filter(
(device) =>
// hide non default devices, unless they have a connected client or plugins
canBeDefaultDevice(device) ||
device.hasDevicePlugins ||
getClientsByDevice(device, clients).length > 0,
);
},
);
export const hasSelectableDevices = createSelector(
getSelectableDevices,
(selectableDevices) => selectableDevices.length > 0,
);
export const getActiveDevice = createSelector(
getSelectedDevice,
getActiveClient,