firmware: disable buttons when DFU in progress

This avoids trying to perform two DFU operations on the same device
at one time. Flashing is so fast, this seems the better option than
trying to support flashing more than one device at a time.

Fixes: https://github.com/pybricks/support/issues/1146
This commit is contained in:
David Lechner
2023-07-12 11:42:53 -05:00
committed by David Lechner
parent 2aea540d23
commit 7bf108087f
5 changed files with 75 additions and 5 deletions
+4
View File
@@ -4,6 +4,10 @@
## [Unreleased]
### Fixed
- Fixed starting DFU flash while another was still in progress ([support#1146]).
[support#1146]: https://github.com/pybricks/support/issues/1146
## [2.2.0-beta.8] - 2023-07-07
### Changed
@@ -450,6 +450,11 @@ const BootloaderModePanel: React.FunctionComponent<BootloaderModePanelProps> = (
export const InstallPybricksDialog: React.FunctionComponent = () => {
const { isOpen } = useSelector((s) => s.firmware.installPybricksDialog);
const inProgress = useSelector(
(s) =>
s.firmware.isFirmwareFlashUsbDfuInProgress ||
s.firmware.isFirmwareRestoreOfficialDfuInProgress,
);
const dispatch = useDispatch();
const [hubName, setHubName] = useState('');
const [licenseAccepted, setLicenseAccepted] = useState(false);
@@ -476,6 +481,7 @@ export const InstallPybricksDialog: React.FunctionComponent = () => {
nextButtonProps={{ text: i18n.translate('nextButton.label') }}
finalButtonProps={{
text: i18n.translate('flashFirmwareButton.label'),
disabled: inProgress,
onClick: () =>
dispatch(
firmwareInstallPybricksDialogAccept(
+3 -1
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2021-2022 The Pybricks Authors
// Copyright (c) 2021-2023 The Pybricks Authors
import { AnyAction } from 'redux';
import {
@@ -23,6 +23,8 @@ test('initial state', () => {
"installPybricksDialog": {
"isOpen": false,
},
"isFirmwareFlashUsbDfuInProgress": false,
"isFirmwareRestoreOfficialDfuInProgress": false,
"progress": null,
"restoreOfficialDialog": {
"isOpen": false,
+50 -2
View File
@@ -1,8 +1,19 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2021-2022 The Pybricks Authors
// Copyright (c) 2021-2023 The Pybricks Authors
import { Reducer, combineReducers } from 'redux';
import { didFailToFinish, didFinish, didProgress, didStart } from './actions';
import {
didFailToFinish,
didFinish,
didProgress,
didStart,
firmwareDidFailToFlashUsbDfu,
firmwareDidFailToRestoreOfficialDfu,
firmwareDidFlashUsbDfu,
firmwareDidRestoreOfficialDfu,
firmwareFlashUsbDfu,
firmwareRestoreOfficialDfu,
} from './actions';
import dfuWindowsDriverInstallDialog from './dfuWindowsDriverInstallDialog/reducers';
import installPybricksDialog from './installPybricksDialog/reducers';
import restoreOfficialDialog from './restoreOfficialDialog/reducers';
@@ -31,10 +42,47 @@ const progress: Reducer<number | null> = (state = null, action) => {
return state;
};
const isFirmwareFlashUsbDfuInProgress: Reducer<boolean> = (state = false, action) => {
if (firmwareFlashUsbDfu.matches(action)) {
return true;
}
if (firmwareDidFlashUsbDfu.matches(action)) {
return false;
}
if (firmwareDidFailToFlashUsbDfu.matches(action)) {
return false;
}
return state;
};
const isFirmwareRestoreOfficialDfuInProgress: Reducer<boolean> = (
state = false,
action,
) => {
if (firmwareRestoreOfficialDfu.matches(action)) {
return true;
}
if (firmwareDidRestoreOfficialDfu.matches(action)) {
return false;
}
if (firmwareDidFailToRestoreOfficialDfu.matches(action)) {
return false;
}
return state;
};
export default combineReducers({
dfuWindowsDriverInstallDialog,
installPybricksDialog,
restoreOfficialDialog,
flashing,
progress,
isFirmwareFlashUsbDfuInProgress,
isFirmwareRestoreOfficialDfuInProgress,
});
@@ -9,7 +9,7 @@ import {
MultistepDialog,
} from '@blueprintjs/core';
import classNames from 'classnames';
import React from 'react';
import React, { useCallback } from 'react';
import { useDispatch } from 'react-redux';
import {
legoEducationSpikeRegisteredTrademark,
@@ -46,6 +46,15 @@ const RestoreFirmwarePanel: React.FunctionComponent = () => {
const [hubType] = useHubPickerSelectedHub();
const dispatch = useDispatch();
const i18n = useI18n();
const inProgress = useSelector(
(s) =>
s.firmware.isFirmwareFlashUsbDfuInProgress ||
s.firmware.isFirmwareRestoreOfficialDfuInProgress,
);
const handleRestoreButtonClick = useCallback(() => {
dispatch(firmwareRestoreOfficialDfu(hubType));
}, [dispatch, hubType]);
return (
<div className={classNames(Classes.DIALOG_BODY, Classes.RUNNING_TEXT)}>
@@ -72,7 +81,8 @@ const RestoreFirmwarePanel: React.FunctionComponent = () => {
<div className="pb-spacer" />
<Button
intent={Intent.PRIMARY}
onClick={() => dispatch(firmwareRestoreOfficialDfu(hubType))}
disabled={inProgress}
onClick={handleRestoreButtonClick}
>
{i18n.translate('restoreFirmwarePanel.flashButton')}
</Button>