diff --git a/doctor/package.json b/doctor/package.json index 1693234c7..2aba3fdd4 100644 --- a/doctor/package.json +++ b/doctor/package.json @@ -1,6 +1,6 @@ { "name": "flipper-doctor", - "version": "0.5.0", + "version": "0.6.0", "description": "Utility for checking for issues with a flipper installation", "main": "lib/index.js", "types": "lib/index.d.ts", diff --git a/doctor/src/cli.ts b/doctor/src/cli.ts index b442e26af..5f89d8fd6 100644 --- a/doctor/src/cli.ts +++ b/doctor/src/cli.ts @@ -22,7 +22,8 @@ import {getEnvInfo} from './environmentInfo'; : { label: category.label, results: await Promise.all( - category.healthchecks.map(async ({label, run}) => ({ + category.healthchecks.map(async ({key, label, run}) => ({ + key, label, result: await run(environmentInfo), })), diff --git a/doctor/src/index.ts b/doctor/src/index.ts index 4a7ff1e69..9fbb844dd 100644 --- a/doctor/src/index.ts +++ b/doctor/src/index.ts @@ -33,6 +33,7 @@ export type Healthchecks = { }; export type Healthcheck = { + key: string; label: string; isRequired?: boolean; run: ( @@ -48,6 +49,7 @@ export type CategoryResult = [ { label: string; results: Array<{ + key: string; label: string; isRequired: boolean; result: {hasProblem: boolean}; @@ -63,6 +65,7 @@ export function getHealthchecks(): Healthchecks { isSkipped: false, healthchecks: [ { + key: 'common.openssl', label: 'OpenSSL Installed', run: async (_: EnvironmentInfo) => { const isAvailable = await commandSucceeds('openssl version'); @@ -72,6 +75,7 @@ export function getHealthchecks(): Healthchecks { }, }, { + key: 'common.watchman', label: 'Watchman Installed', run: async (_: EnvironmentInfo) => { const isAvailable = await isWatchmanAvailable(); @@ -88,6 +92,7 @@ export function getHealthchecks(): Healthchecks { isSkipped: false, healthchecks: [ { + key: 'android.sdk', label: 'SDK Installed', isRequired: true, run: async (e: EnvironmentInfo) => ({ @@ -104,6 +109,7 @@ export function getHealthchecks(): Healthchecks { isSkipped: false, healthchecks: [ { + key: 'ios.sdk', label: 'SDK Installed', isRequired: true, run: async (e: EnvironmentInfo) => ({ @@ -111,6 +117,7 @@ export function getHealthchecks(): Healthchecks { }), }, { + key: 'ios.xcode', label: 'XCode Installed', isRequired: true, run: async (e: EnvironmentInfo) => ({ @@ -118,6 +125,7 @@ export function getHealthchecks(): Healthchecks { }), }, { + key: 'ios.xcode-select', label: 'xcode-select set', isRequired: true, run: async (_: EnvironmentInfo) => ({ @@ -125,6 +133,7 @@ export function getHealthchecks(): Healthchecks { }), }, { + key: 'ios.instruments', label: 'Instruments exists', isRequired: true, run: async (_: EnvironmentInfo) => { @@ -164,17 +173,20 @@ export async function runHealthchecks(): Promise< { label: category.label, results: await Promise.all( - category.healthchecks.map(async ({label, run, isRequired}) => ({ - label, - isRequired: isRequired ?? true, - result: await run(environmentInfo).catch(e => { - console.error(e); - // TODO Improve result type to be: OK | Problem(message, fix...) - return { - hasProblem: true, - }; + category.healthchecks.map( + async ({key, label, run, isRequired}) => ({ + key, + label, + isRequired: isRequired ?? true, + result: await run(environmentInfo).catch(e => { + console.error(e); + // TODO Improve result type to be: OK | Problem(message, fix...) + return { + hasProblem: true, + }; + }), }), - })), + ), ), }, ]; diff --git a/src/chrome/DoctorBar.tsx b/src/chrome/DoctorBar.tsx index 7ce263cf9..2aefe4fc7 100644 --- a/src/chrome/DoctorBar.tsx +++ b/src/chrome/DoctorBar.tsx @@ -23,14 +23,14 @@ import runHealthchecks, { HealthcheckEventsHandler, } from '../utils/runHealthchecks'; import { + HealthcheckResult, updateHealthcheckResult, startHealthchecks, finishHealthchecks, - HealthcheckStatus, } from '../reducers/healthchecks'; type StateFromProps = { - healthcheckStatus: HealthcheckStatus; + healthcheckResult: HealthcheckResult; } & HealthcheckSettings; type DispatchFromProps = { @@ -52,7 +52,11 @@ class DoctorBar extends Component { } async showMessageIfChecksFailed() { await runHealthchecks(this.props); - if (this.props.healthcheckStatus === 'FAILED') { + if ( + (this.props.healthcheckResult.status === 'FAILED' || + this.props.healthcheckResult.status === 'WARNING') && + !this.props.healthcheckResult.isAcknowledged + ) { this.setVisible(true); } } @@ -99,11 +103,11 @@ export default connect( ({ settingsState: {enableAndroid}, healthchecks: { - healthcheckReport: {status}, + healthcheckReport: {result}, }, }) => ({ enableAndroid, - healthcheckStatus: status, + healthcheckResult: result, }), { setActiveSheet, diff --git a/src/chrome/DoctorSheet.tsx b/src/chrome/DoctorSheet.tsx index 302cb328f..27cf34300 100644 --- a/src/chrome/DoctorSheet.tsx +++ b/src/chrome/DoctorSheet.tsx @@ -26,14 +26,12 @@ import {State as Store} from '../reducers'; import { HealthcheckResult, HealthcheckReportCategory, - HealthcheckReportItem, HealthcheckReport, startHealthchecks, finishHealthchecks, updateHealthcheckResult, acknowledgeProblems, resetAcknowledgedProblems, - HealthcheckStatus, } from '../reducers/healthchecks'; import runHealthchecks, { HealthcheckSettings, @@ -123,17 +121,18 @@ function CenteredCheckbox(props: { ); } -function HealthcheckIcon(props: {check: HealthcheckResult}) { - switch (props.check.status) { +function HealthcheckIcon(props: {checkResult: HealthcheckResult}) { + const {checkResult: check} = props; + switch (props.checkResult.status) { case 'IN_PROGRESS': - return ; + return ; case 'SKIPPED': return ( ); case 'SUCCESS': @@ -142,7 +141,7 @@ function HealthcheckIcon(props: {check: HealthcheckResult}) { size={16} name={'checkmark'} color={colors.green} - title={props.check.message} + title={props.checkResult.message} /> ); case 'FAILED': @@ -151,17 +150,8 @@ function HealthcheckIcon(props: {check: HealthcheckResult}) { size={16} name={'cross'} color={colors.red} - title={props.check.message} - /> - ); - case 'FAILED_ACKNOWLEDGED': - return ( - ); default: @@ -170,26 +160,26 @@ function HealthcheckIcon(props: {check: HealthcheckResult}) { size={16} name={'caution'} color={colors.yellow} - title={props.check.message} + title={props.checkResult.message} /> ); } } function HealthcheckDisplay(props: { - category: HealthcheckReportCategory; - check: HealthcheckReportItem; + label: string; + result: HealthcheckResult; onClick?: () => void; }) { return ( - - + + - {props.check.label} + {props.label} @@ -221,20 +211,13 @@ function SideMessageDisplay(props: { } } -function hasProblems(status: HealthcheckStatus) { - return ( - status === 'FAILED' || - status === 'FAILED_ACKNOWLEDGED' || - status === 'WARNING' - ); +function hasProblems(result: HealthcheckResult) { + const {status} = result; + return status === 'FAILED' || status === 'WARNING'; } -function hasFailedChecks(status: HealthcheckStatus) { - return status === 'FAILED' || status === 'FAILED_ACKNOWLEDGED'; -} - -function hasNewFailedChecks(status: HealthcheckStatus) { - return status === 'FAILED'; +function hasNewProblems(result: HealthcheckResult) { + return hasProblems(result) && !result.isAcknowledged; } export type State = { @@ -254,21 +237,21 @@ class DoctorSheet extends Component { static getDerivedStateFromProps(props: Props, state: State): State | null { if ( !state.acknowledgeCheckboxVisible && - hasFailedChecks(props.healthcheckReport.status) + hasProblems(props.healthcheckReport.result) ) { return { ...state, acknowledgeCheckboxVisible: true, acknowledgeOnClose: state.acknowledgeOnClose === undefined - ? !hasNewFailedChecks(props.healthcheckReport.status) + ? !hasNewProblems(props.healthcheckReport.result) : state.acknowledgeOnClose, }; } if ( state.acknowledgeCheckboxVisible && - !hasFailedChecks(props.healthcheckReport.status) + !hasProblems(props.healthcheckReport.result) ) { return { ...state, @@ -296,8 +279,8 @@ class DoctorSheet extends Component { }); } - openHelpUrl(check: HealthcheckReportItem): void { - check.helpUrl && shell.openExternal(check.helpUrl); + openHelpUrl(helpUrl?: string): void { + helpUrl && shell.openExternal(helpUrl); } async runHealthchecks() { @@ -311,29 +294,34 @@ class DoctorSheet extends Component { {Object.values(this.props.healthcheckReport.categories).map( - (category: HealthcheckReportCategory, categoryIdx: number) => { + (category: HealthcheckReportCategory) => { return ( - - - {category.status !== 'SKIPPED' && ( + + + {category.result.status !== 'SKIPPED' && ( - {category.checks.map((check, checkIdx) => ( + {Object.values(category.checks).map(check => ( this.openHelpUrl(check) + check.result.helpUrl + ? () => this.openHelpUrl(check.result.helpUrl) : undefined } /> ))} )} - {category.status === 'SKIPPED' && ( + {category.result.status === 'SKIPPED' && ( - {category.message} + + {category.result.message} + )} @@ -345,9 +333,9 @@ class DoctorSheet extends Component { @@ -366,7 +354,9 @@ class DoctorSheet extends Component { Close