Make FlashStep a PureComponent

Change-type: patch
This commit is contained in:
Alexis Svinartchouk 2020-05-26 18:06:13 +02:00
parent afa29a0ed1
commit 0ebfecc60c
3 changed files with 59 additions and 28 deletions

View File

@ -48,7 +48,7 @@ export function fromFlashState({
type, type,
percentage, percentage,
position, position,
}: FlashState): string { }: Pick<FlashState, 'type' | 'percentage' | 'position'>): string {
if (type === undefined) { if (type === undefined) {
return 'Starting...'; return 'Starting...';
} else if (type === 'decompressing') { } else if (type === 'decompressing') {

View File

@ -77,6 +77,7 @@ const getErrorMessageFromCode = (errorCode: string) => {
}; };
async function flashImageToDrive( async function flashImageToDrive(
isFlashing: boolean,
goToSuccess: () => void, goToSuccess: () => void,
sourceOptions: SourceOptions, sourceOptions: SourceOptions,
): Promise<string> { ): Promise<string> {
@ -86,7 +87,7 @@ async function flashImageToDrive(
return _.includes(devices, drive.device); return _.includes(devices, drive.device);
}); });
if (drives.length === 0 || flashState.isFlashing()) { if (drives.length === 0 || isFlashing) {
return ''; return '';
} }
@ -132,11 +133,18 @@ async function flashImageToDrive(
return ''; return '';
} }
const getProgressButtonLabel = () => { const getProgressButtonLabel = (
if (!flashState.isFlashing()) { isFlashing: boolean,
// TODO: factorize
type: 'decompressing' | 'flashing' | 'verifying',
position: number,
percentage?: number,
) => {
// TODO
if (!isFlashing) {
return 'Flash!'; return 'Flash!';
} }
return progressStatus.fromFlashState(flashState.getFlashState()); return progressStatus.fromFlashState({ type, position, percentage });
}; };
const formatSeconds = (totalSeconds: number) => { const formatSeconds = (totalSeconds: number) => {
@ -159,6 +167,14 @@ interface FlashStepProps {
shouldFlashStepBeDisabled: boolean; shouldFlashStepBeDisabled: boolean;
goToSuccess: () => void; goToSuccess: () => void;
source: SourceOptions; source: SourceOptions;
isFlashing: boolean;
// TODO: factorize
step: 'decompressing' | 'flashing' | 'verifying';
percentage: number;
position: number;
failed: number;
speed?: number;
eta?: number;
} }
interface FlashStepState { interface FlashStepState {
@ -167,7 +183,10 @@ interface FlashStepState {
showDriveSelectorModal: boolean; showDriveSelectorModal: boolean;
} }
export class FlashStep extends React.Component<FlashStepProps, FlashStepState> { export class FlashStep extends React.PureComponent<
FlashStepProps,
FlashStepState
> {
constructor(props: FlashStepProps) { constructor(props: FlashStepProps) {
super(props); super(props);
this.state = { this.state = {
@ -185,6 +204,7 @@ export class FlashStep extends React.Component<FlashStepProps, FlashStepState> {
} }
this.setState({ this.setState({
errorMessage: await flashImageToDrive( errorMessage: await flashImageToDrive(
this.props.isFlashing,
this.props.goToSuccess, this.props.goToSuccess,
this.props.source, this.props.source,
), ),
@ -210,7 +230,7 @@ export class FlashStep extends React.Component<FlashStepProps, FlashStepState> {
return _.includes(devices, drive.device); return _.includes(devices, drive.device);
}, },
); );
if (drives.length === 0 || flashState.isFlashing()) { if (drives.length === 0 || this.props.isFlashing) {
return; return;
} }
const hasDangerStatus = constraints.hasListDriveImageCompatibilityStatus( const hasDangerStatus = constraints.hasListDriveImageCompatibilityStatus(
@ -223,6 +243,7 @@ export class FlashStep extends React.Component<FlashStepProps, FlashStepState> {
} }
this.setState({ this.setState({
errorMessage: await flashImageToDrive( errorMessage: await flashImageToDrive(
this.props.isFlashing,
this.props.goToSuccess, this.props.goToSuccess,
this.props.source, this.props.source,
), ),
@ -230,9 +251,6 @@ export class FlashStep extends React.Component<FlashStepProps, FlashStepState> {
} }
public render() { public render() {
const state = flashState.getFlashState();
const isFlashing = flashState.isFlashing();
const flashErrorCode = flashState.getLastFlashErrorCode();
return ( return (
<> <>
<div className="box text-center"> <div className="box text-center">
@ -246,49 +264,54 @@ export class FlashStep extends React.Component<FlashStepProps, FlashStepState> {
<div className="space-vertical-large"> <div className="space-vertical-large">
<StepSelection> <StepSelection>
<ProgressButton <ProgressButton
type={state.type} type={this.props.step}
active={isFlashing} active={this.props.isFlashing}
percentage={state.percentage} percentage={this.props.percentage}
label={getProgressButtonLabel()} label={getProgressButtonLabel(
disabled={ this.props.isFlashing,
Boolean(flashErrorCode) || this.props.step,
this.props.shouldFlashStepBeDisabled this.props.position,
} this.props.percentage,
)}
disabled={this.props.shouldFlashStepBeDisabled}
callback={() => { callback={() => {
this.tryFlash(); this.tryFlash();
}} }}
/> />
{isFlashing && ( {this.props.isFlashing && (
<IconButton <IconButton
icon={<FontAwesomeIcon icon={faTimes} />} icon={<FontAwesomeIcon icon={faTimes} />}
plain plain
onClick={imageWriter.cancel} onClick={imageWriter.cancel}
color="#fff" color="#fff"
hoverIndicator={{ dark: true }}
/> />
)} )}
</StepSelection> </StepSelection>
{!_.isNil(state.speed) && {!_.isNil(this.props.speed) &&
state.percentage !== COMPLETED_PERCENTAGE && ( this.props.percentage !== COMPLETED_PERCENTAGE && (
<p className="step-footer step-footer-split"> <p className="step-footer step-footer-split">
{Boolean(state.speed) && ( {Boolean(this.props.speed) && (
<span>{`${state.speed.toFixed( <span>{`${this.props.speed.toFixed(
SPEED_PRECISION, SPEED_PRECISION,
)} MB/s`}</span> )} MB/s`}</span>
)} )}
{!_.isNil(state.eta) && ( {!_.isNil(this.props.eta) && (
<span>{`ETA: ${formatSeconds(state.eta)}`}</span> <span>{`ETA: ${formatSeconds(this.props.eta)}`}</span>
)} )}
</p> </p>
)} )}
{Boolean(state.failed) && ( {Boolean(this.props.failed) && (
<div className="target-status-wrap"> <div className="target-status-wrap">
<div className="target-status-line target-status-failed"> <div className="target-status-line target-status-failed">
<span className="target-status-dot"></span> <span className="target-status-dot"></span>
<span className="target-status-quantity">{state.failed}</span> <span className="target-status-quantity">
{this.props.failed}
</span>
<span className="target-status-message"> <span className="target-status-message">
{messages.progress.failed(state.failed)}{' '} {messages.progress.failed(this.props.failed)}{' '}
</span> </span>
</div> </div>
</div> </div>

View File

@ -131,6 +131,7 @@ export class MainPage extends React.Component<
} }
private renderMain() { private renderMain() {
const state = flashState.getFlashState();
const shouldDriveStepBeDisabled = !this.state.hasImage; const shouldDriveStepBeDisabled = !this.state.hasImage;
const shouldFlashStepBeDisabled = const shouldFlashStepBeDisabled =
!this.state.hasImage || !this.state.hasDrive; !this.state.hasImage || !this.state.hasDrive;
@ -249,6 +250,13 @@ export class MainPage extends React.Component<
goToSuccess={() => this.setState({ current: 'success' })} goToSuccess={() => this.setState({ current: 'success' })}
shouldFlashStepBeDisabled={shouldFlashStepBeDisabled} shouldFlashStepBeDisabled={shouldFlashStepBeDisabled}
source={this.state.source} source={this.state.source}
isFlashing={flashState.isFlashing()}
step={state.type}
percentage={state.percentage}
position={state.position}
failed={state.failed}
speed={state.speed}
eta={state.eta}
/> />
</div> </div>
</Flex> </Flex>