Allow disabling iOS development in Settings
Summary: Currently Android development can be disabled in Settings, but iOS development not. Because of this Doctor always shows warnings to Android-only developers who has no iOS SDK installed. This change makes it possible to disable "iOS development" option in the same way as we already had for Android. Additionally I changed Doctor warning to show more specific message if only iOS or only Android checks are failed with suggestion to disable the failing platform if it is not required. Reviewed By: jknoxville Differential Revision: D19538070 fbshipit-source-id: 234d2c6cf21083f9d6aebd63418aed7f9a78e922
This commit is contained in:
committed by
Facebook Github Bot
parent
b625efee3d
commit
aab004aa15
@@ -14,6 +14,7 @@ import {
|
||||
setActiveSheet,
|
||||
ActiveSheet,
|
||||
ACTIVE_SHEET_DOCTOR,
|
||||
ACTIVE_SHEET_SETTINGS,
|
||||
} from '../reducers/application';
|
||||
import {State as Store} from '../reducers/index';
|
||||
import {ButtonGroup, Button} from 'flipper';
|
||||
@@ -23,23 +24,24 @@ import runHealthchecks, {
|
||||
HealthcheckEventsHandler,
|
||||
} from '../utils/runHealthchecks';
|
||||
import {
|
||||
HealthcheckResult,
|
||||
updateHealthcheckResult,
|
||||
startHealthchecks,
|
||||
finishHealthchecks,
|
||||
HealthcheckReport,
|
||||
HealthcheckResult,
|
||||
} from '../reducers/healthchecks';
|
||||
|
||||
import {reportUsage} from '../utils/metrics';
|
||||
|
||||
type StateFromProps = {
|
||||
healthcheckResult: HealthcheckResult;
|
||||
healthcheckReport: HealthcheckReport;
|
||||
} & HealthcheckSettings;
|
||||
|
||||
type DispatchFromProps = {
|
||||
setActiveSheet: (payload: ActiveSheet) => void;
|
||||
} & HealthcheckEventsHandler;
|
||||
|
||||
type State = {visible: boolean};
|
||||
type State = {visible: boolean; message: string; showSettingsButton: boolean};
|
||||
|
||||
type Props = DispatchFromProps & StateFromProps;
|
||||
class DoctorBar extends Component<Props, State> {
|
||||
@@ -47,18 +49,41 @@ class DoctorBar extends Component<Props, State> {
|
||||
super(props);
|
||||
this.state = {
|
||||
visible: false,
|
||||
message: '',
|
||||
showSettingsButton: false,
|
||||
};
|
||||
}
|
||||
componentDidMount() {
|
||||
this.showMessageIfChecksFailed();
|
||||
}
|
||||
static getDerivedStateFromProps(props: Props, state: State): State | null {
|
||||
const failedCategories = Object.values(
|
||||
props.healthcheckReport.categories,
|
||||
).filter(cat => hasProblems(cat.result));
|
||||
if (failedCategories.length == 1) {
|
||||
const failedCat = failedCategories[0];
|
||||
if (failedCat.key === 'ios' || failedCat.key === 'android') {
|
||||
return {
|
||||
...state,
|
||||
message: `Doctor has discovered problems with your ${failedCat.label} setup. If you are not interested in ${failedCat.label} development you can disable it in Settings.`,
|
||||
showSettingsButton: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
if (failedCategories.length) {
|
||||
return {
|
||||
...state,
|
||||
message: 'Doctor has discovered problems with your installation.',
|
||||
showSettingsButton: false,
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
async showMessageIfChecksFailed() {
|
||||
await runHealthchecks(this.props);
|
||||
if (
|
||||
this.props.healthcheckResult.status === 'FAILED' ||
|
||||
this.props.healthcheckResult.status === 'WARNING'
|
||||
) {
|
||||
if (this.props.healthcheckResult.isAcknowledged) {
|
||||
const result = this.props.healthcheckReport.result;
|
||||
if (hasProblems(result)) {
|
||||
if (result.isAcknowledged) {
|
||||
reportUsage('doctor:warning:suppressed');
|
||||
} else {
|
||||
this.setVisible(true);
|
||||
@@ -76,18 +101,28 @@ class DoctorBar extends Component<Props, State> {
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
onClick={() => {
|
||||
reportUsage('doctor:report:opened:fromWarningBar');
|
||||
this.props.setActiveSheet(ACTIVE_SHEET_DOCTOR);
|
||||
this.setVisible(false);
|
||||
}}>
|
||||
Show Problems
|
||||
</Button>
|
||||
{this.state.showSettingsButton && (
|
||||
<Button
|
||||
onClick={() => {
|
||||
reportUsage('settings:opened:fromWarningBar');
|
||||
this.props.setActiveSheet(ACTIVE_SHEET_SETTINGS);
|
||||
}}>
|
||||
Show Settings
|
||||
</Button>
|
||||
)}
|
||||
<Button onClick={() => this.setVisible(false)}>
|
||||
Dismiss
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
</ButtonSection>
|
||||
<FlexColumn style={{flexGrow: 1}}>
|
||||
Doctor has discovered problems with your installation
|
||||
{this.state.message}
|
||||
</FlexColumn>
|
||||
</FlexRow>
|
||||
</WarningContainer>
|
||||
@@ -107,13 +142,12 @@ class DoctorBar extends Component<Props, State> {
|
||||
|
||||
export default connect<StateFromProps, DispatchFromProps, {}, Store>(
|
||||
({
|
||||
settingsState: {enableAndroid},
|
||||
healthchecks: {
|
||||
healthcheckReport: {result},
|
||||
},
|
||||
settingsState: {enableAndroid, enableIOS},
|
||||
healthchecks: {healthcheckReport},
|
||||
}) => ({
|
||||
enableAndroid,
|
||||
healthcheckResult: result,
|
||||
enableIOS,
|
||||
healthcheckReport,
|
||||
}),
|
||||
{
|
||||
setActiveSheet,
|
||||
@@ -149,3 +183,7 @@ const ButtonSection = styled(FlexColumn)({
|
||||
flexShrink: 0,
|
||||
flexGrow: 0,
|
||||
});
|
||||
|
||||
function hasProblems(result: HealthcheckResult) {
|
||||
return result.status === 'WARNING' || result.status === 'FAILED';
|
||||
}
|
||||
|
||||
@@ -201,7 +201,7 @@ function ResultMessage(props: {result: HealthcheckResult}) {
|
||||
return (
|
||||
<p>
|
||||
Doctor has discovered problems with your installation. Please click to
|
||||
each item to get details.
|
||||
an item to get its details.
|
||||
</p>
|
||||
);
|
||||
} else {
|
||||
@@ -404,9 +404,13 @@ class DoctorSheet extends Component<Props, State> {
|
||||
}
|
||||
|
||||
export default connect<StateFromProps, DispatchFromProps, OwnProps, Store>(
|
||||
({healthchecks: {healthcheckReport}, settingsState}) => ({
|
||||
({
|
||||
healthchecks: {healthcheckReport},
|
||||
settingsState: {enableAndroid, enableIOS},
|
||||
}) => ({
|
||||
healthcheckReport,
|
||||
enableAndroid: settingsState.enableAndroid,
|
||||
enableAndroid,
|
||||
enableIOS,
|
||||
}),
|
||||
{
|
||||
startHealthchecks,
|
||||
|
||||
@@ -24,6 +24,10 @@ import {FilePathConfigField, ConfigText} from './settings/configFields';
|
||||
import isEqual from 'lodash.isequal';
|
||||
import restartFlipper from '../utils/restartFlipper';
|
||||
import LauncherSettingsPanel from '../fb-stubs/LauncherSettingsPanel';
|
||||
import {reportUsage} from '../utils/metrics';
|
||||
import os from 'os';
|
||||
|
||||
const platform = os.platform();
|
||||
|
||||
const Container = styled(FlexColumn)({
|
||||
padding: 20,
|
||||
@@ -64,6 +68,10 @@ class SettingsSheet extends Component<Props, State> {
|
||||
updatedLauncherSettings: {...this.props.launcherSettings},
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
reportUsage('settings:opened');
|
||||
}
|
||||
|
||||
applyChanges = async () => {
|
||||
this.props.updateSettings(this.state.updatedSettings);
|
||||
this.props.updateLauncherSettings(this.state.updatedLauncherSettings);
|
||||
@@ -104,15 +112,26 @@ class SettingsSheet extends Component<Props, State> {
|
||||
</ToggledSection>
|
||||
<ToggledSection
|
||||
label="iOS Developer"
|
||||
toggled={this.props.isXcodeDetected}
|
||||
frozen>
|
||||
toggled={
|
||||
this.state.updatedSettings.enableIOS && platform === 'darwin'
|
||||
}
|
||||
frozen={platform !== 'darwin'}
|
||||
onChange={v => {
|
||||
this.setState({
|
||||
updatedSettings: {...this.state.updatedSettings, enableIOS: v},
|
||||
});
|
||||
}}>
|
||||
{' '}
|
||||
<ConfigText
|
||||
content={
|
||||
'Use xcode-select to enable or switch between xcode versions'
|
||||
}
|
||||
frozen
|
||||
/>
|
||||
{platform === 'darwin' && (
|
||||
<ConfigText
|
||||
content={'Use "xcode-select" to switch between Xcode versions'}
|
||||
/>
|
||||
)}
|
||||
{platform !== 'darwin' && (
|
||||
<ConfigText
|
||||
content={'iOS development is only supported on MacOS'}
|
||||
/>
|
||||
)}
|
||||
</ToggledSection>
|
||||
<LauncherSettingsPanel
|
||||
isPrefetchingEnabled={this.state.updatedSettings.enablePrefetching}
|
||||
|
||||
@@ -42,6 +42,7 @@ import isProduction from '../utils/isProduction';
|
||||
import {clipboard} from 'electron';
|
||||
import React from 'react';
|
||||
import {State} from 'src/reducers';
|
||||
import {reportUsage} from '../utils/metrics';
|
||||
|
||||
const AppTitleBar = styled(FlexRow)<{focused?: boolean}>(({focused}) => ({
|
||||
background: focused
|
||||
@@ -175,7 +176,10 @@ class TitleBar extends React.Component<Props, StateFromProps> {
|
||||
icon="settings"
|
||||
title="Settings"
|
||||
compact={true}
|
||||
onClick={() => this.props.setActiveSheet(ACTIVE_SHEET_SETTINGS)}
|
||||
onClick={() => {
|
||||
this.props.setActiveSheet(ACTIVE_SHEET_SETTINGS);
|
||||
reportUsage('settings:opened:fromTitleBar');
|
||||
}}
|
||||
/>
|
||||
{config.bugReportButtonVisible && (
|
||||
<Button
|
||||
@@ -189,7 +193,10 @@ class TitleBar extends React.Component<Props, StateFromProps> {
|
||||
icon="first-aid"
|
||||
title="Doctor"
|
||||
compact={true}
|
||||
onClick={() => this.props.setActiveSheet(ACTIVE_SHEET_DOCTOR)}
|
||||
onClick={() => {
|
||||
this.props.setActiveSheet(ACTIVE_SHEET_DOCTOR);
|
||||
reportUsage('doctor:report:opened:fromTitleBar');
|
||||
}}
|
||||
/>
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
|
||||
@@ -255,6 +255,9 @@ export default (store: Store, logger: Logger) => {
|
||||
if (process.platform !== 'darwin') {
|
||||
return;
|
||||
}
|
||||
if (!store.getState().settingsState.enableIOS) {
|
||||
return;
|
||||
}
|
||||
isXcodeDetected()
|
||||
.then(isDetected => {
|
||||
store.dispatch(setXcodeDetected(isDetected));
|
||||
|
||||
@@ -20,6 +20,7 @@ export enum Tristate {
|
||||
export type Settings = {
|
||||
androidHome: string;
|
||||
enableAndroid: boolean;
|
||||
enableIOS: boolean;
|
||||
/**
|
||||
* If unset, this will assume the value of the GK setting.
|
||||
* Note that this setting has no effect in the open source version
|
||||
@@ -47,6 +48,7 @@ export const DEFAULT_ANDROID_SDK_PATH = getDefaultAndroidSdkPath();
|
||||
const initialState: Settings = {
|
||||
androidHome: getDefaultAndroidSdkPath(),
|
||||
enableAndroid: true,
|
||||
enableIOS: os.platform() === 'darwin',
|
||||
enablePrefetching: Tristate.Unset,
|
||||
jsApps: {
|
||||
webAppLauncher: {
|
||||
|
||||
@@ -26,6 +26,7 @@ export type HealthcheckEventsHandler = {
|
||||
|
||||
export type HealthcheckSettings = {
|
||||
enableAndroid: boolean;
|
||||
enableIOS: boolean;
|
||||
};
|
||||
|
||||
export type HealthcheckOptions = HealthcheckEventsHandler & HealthcheckSettings;
|
||||
@@ -40,6 +41,14 @@ async function launchHealthchecks(options: HealthcheckOptions): Promise<void> {
|
||||
'Healthcheck is skipped, because "Android Development" option is disabled in the Flipper settings',
|
||||
};
|
||||
}
|
||||
if (!options.enableIOS) {
|
||||
healthchecks.ios = {
|
||||
label: healthchecks.ios.label,
|
||||
isSkipped: true,
|
||||
skipReason:
|
||||
'Healthcheck is skipped, because "iOS Development" option is disabled in the Flipper settings',
|
||||
};
|
||||
}
|
||||
options.startHealthchecks(healthchecks);
|
||||
const environmentInfo = await getEnvInfo();
|
||||
let hasProblems = false;
|
||||
|
||||
Reference in New Issue
Block a user