diff --git a/src/firmware/actions.ts b/src/firmware/actions.ts index 8a4bc484e..77d1929d0 100644 --- a/src/firmware/actions.ts +++ b/src/firmware/actions.ts @@ -4,6 +4,7 @@ import { FirmwareReaderError, HubType } from '@pybricks/firmware'; import { createAction } from '../actions'; import { Hub } from '../components/hubPicker'; +import { isError } from '../utils'; export enum MetadataProblem { Missing = 'metadata.missing', @@ -131,29 +132,6 @@ export const flashFirmware = createAction( }), ); -/** - * Action that indicates flashing firmware started. - * @param total The total number of bytes to be flashed. - */ -export const didStart = createAction(() => ({ - type: 'flashFirmware.action.didStart', -})); - -/** Action that indicates that flashing firmware completed successfully. */ -export const didFinish = createAction(() => ({ - type: 'flashFirmware.action.didFinish', -})); - -function isError(err: unknown): err is Error { - const maybeError = err as Error; - - return ( - maybeError !== undefined && - typeof maybeError.name === 'string' && - typeof maybeError.message === 'string' - ); -} - // FIXME: get rid of this monstrosity const didFailToFinishType = 'flashFirmware.action.didFailToFinish'; diff --git a/src/firmware/reducers.test.ts b/src/firmware/reducers.test.ts index 1bbd527ad..3a37cb2d2 100644 --- a/src/firmware/reducers.test.ts +++ b/src/firmware/reducers.test.ts @@ -2,15 +2,8 @@ // Copyright (c) 2021-2026 The Pybricks Authors import { AnyAction } from 'redux'; -import { - FailToFinishReasonType, - didFailToFinish, - didFinish, - didStart, -} from './actions'; -import reducers from './reducers'; -type State = ReturnType; +import reducers from './reducers'; test('initial state', () => { expect(reducers(undefined, {} as AnyAction)).toMatchInlineSnapshot(` @@ -18,7 +11,6 @@ test('initial state', () => { "dfuWindowsDriverInstallDialog": { "isOpen": false, }, - "flashing": false, "installPybricksDialog": { "isOpen": false, }, @@ -31,14 +23,3 @@ test('initial state', () => { } `); }); - -test('flashing', () => { - expect(reducers({ flashing: false } as State, didStart()).flashing).toBe(true); - expect(reducers({ flashing: true } as State, didFinish()).flashing).toBe(false); - expect( - reducers( - { flashing: true } as State, - didFailToFinish(FailToFinishReasonType.TimedOut), - ).flashing, - ).toBe(false); -}); diff --git a/src/firmware/reducers.ts b/src/firmware/reducers.ts index acd3e6227..e6306219f 100644 --- a/src/firmware/reducers.ts +++ b/src/firmware/reducers.ts @@ -3,9 +3,6 @@ import { Reducer, combineReducers } from 'redux'; import { - didFailToFinish, - didFinish, - didStart, firmwareDidFailToFlashUsbDfu, firmwareDidFailToRestoreOfficialDfu, firmwareDidFailToRestoreOfficialEV3, @@ -20,18 +17,6 @@ import dfuWindowsDriverInstallDialog from './dfuWindowsDriverInstallDialog/reduc import installPybricksDialog from './installPybricksDialog/reducers'; import restoreOfficialDialog from './restoreOfficialDialog/reducers'; -const flashing: Reducer = (state = false, action) => { - if (didStart.matches(action)) { - return true; - } - - if (didFinish.matches(action) || didFailToFinish.matches(action)) { - return false; - } - - return state; -}; - const isFirmwareFlashUsbDfuInProgress: Reducer = (state = false, action) => { if (firmwareFlashUsbDfu.matches(action)) { return true; @@ -86,7 +71,6 @@ export default combineReducers({ dfuWindowsDriverInstallDialog, installPybricksDialog, restoreOfficialDialog, - flashing, isFirmwareFlashUsbDfuInProgress, isFirmwareRestoreOfficialDfuInProgress, isFirmwareFlashEV3InProgress, diff --git a/src/firmware/sagas.test.ts b/src/firmware/sagas.test.ts index 97d446a40..5af6da28f 100644 --- a/src/firmware/sagas.test.ts +++ b/src/firmware/sagas.test.ts @@ -42,8 +42,6 @@ import { HubError, MetadataProblem, didFailToFinish, - didFinish, - didStart, flashFirmware as flashFirmwareAction, } from './actions'; import flashFirmware from './sagas'; @@ -124,12 +122,6 @@ describe('flashFirmware', () => { const mpyBinaryData = new Uint8Array(mpySize); saga.put(didCompile(mpyBinaryData)); - // then start flashing the firmware - - // should get didStart action just before starting to erase - action = await saga.take(); - expect(action).toEqual(didStart()); - // erase first action = await saga.take(); @@ -232,9 +224,6 @@ describe('flashFirmware', () => { // then we are done - action = await saga.take(); - expect(action).toEqual(didFinish()); - await saga.end(); }); @@ -284,12 +273,6 @@ describe('flashFirmware', () => { saga.put(didRequest(0)); saga.put(infoResponse(0x01000000, 0x08005000, 0x081f800, HubType.MoveHub)); - // then start flashing the firmware - - // should get didStart action just before starting to erase - action = await saga.take(); - expect(action).toEqual(didStart()); - // erase first action = await saga.take(); @@ -392,9 +375,6 @@ describe('flashFirmware', () => { // then we are done - action = await saga.take(); - expect(action).toEqual(didFinish()); - await saga.end(); }); @@ -1008,12 +988,6 @@ describe('flashFirmware', () => { const mpyBinaryData = new Uint8Array(mpySize); saga.put(didCompile(mpyBinaryData)); - // then start flashing the firmware - - // should get didStart action just before starting to erase - action = await saga.take(); - expect(action).toEqual(didStart()); - // erase first action = await saga.take(); @@ -1121,12 +1095,6 @@ describe('flashFirmware', () => { const mpyBinaryData = new Uint8Array(mpySize); saga.put(didCompile(mpyBinaryData)); - // then start flashing the firmware - - // should get didStart action just before starting to erase - action = await saga.take(); - expect(action).toEqual(didStart()); - // erase first action = await saga.take(); @@ -1243,12 +1211,6 @@ describe('flashFirmware', () => { const mpyBinaryData = new Uint8Array(mpySize); saga.put(didCompile(mpyBinaryData)); - // then start flashing the firmware - - // should get didStart action just before starting to erase - action = await saga.take(); - expect(action).toEqual(didStart()); - // erase first action = await saga.take(); @@ -1416,12 +1378,6 @@ describe('flashFirmware', () => { const mpyBinaryData = new Uint8Array(mpySize); saga.put(didCompile(mpyBinaryData)); - // then start flashing the firmware - - // should get didStart action just before starting to erase - action = await saga.take(); - expect(action).toEqual(didStart()); - // erase first action = await saga.take(); @@ -1594,12 +1550,6 @@ describe('flashFirmware', () => { saga.put(didRequest(0)); saga.put(infoResponse(0x01000000, 0x08005000, 0x081f800, HubType.MoveHub)); - // then start flashing the firmware - - // should get didStart action just before starting to erase - action = await saga.take(); - expect(action).toEqual(didStart()); - // erase first action = await saga.take(); @@ -1703,9 +1653,6 @@ describe('flashFirmware', () => { // then we are done - action = await saga.take(); - expect(action).toEqual(didFinish()); - await saga.end(); }); @@ -2156,12 +2103,6 @@ describe('flashFirmware', () => { const mpyBinaryData = new Uint8Array(mpySize); saga.put(didCompile(mpyBinaryData)); - // then start flashing the firmware - - // should get didStart action just before starting to erase - action = await saga.take(); - expect(action).toEqual(didStart()); - // erase first action = await saga.take(); @@ -2262,9 +2203,6 @@ describe('flashFirmware', () => { // then we are done - action = await saga.take(); - expect(action).toEqual(didFinish()); - await saga.end(); }); }); diff --git a/src/firmware/sagas.ts b/src/firmware/sagas.ts index f6f938f33..946b14478 100644 --- a/src/firmware/sagas.ts +++ b/src/firmware/sagas.ts @@ -74,8 +74,6 @@ import { HubError, MetadataProblem, didFailToFinish, - didFinish, - didStart, firmwareDidFailToFlashEV3, firmwareDidFailToFlashUsbDfu, firmwareDidFailToRestoreOfficialDfu, @@ -465,8 +463,6 @@ function* handleFlashFirmware(action: ReturnType): Generat } } - yield* put(didStart()); - yield* put( alertsShowAlert( 'firmware', @@ -630,8 +626,6 @@ function* handleFlashFirmware(action: ReturnType): Generat // this will cause the remote device to disconnect and reboot const rebootAction = yield* put(rebootRequest(nextMessageId())); yield* waitForDidRequest(rebootAction.id); - - yield* put(didFinish()); } catch (err) { yield* put(didFailToFinish(FailToFinishReasonType.Unknown, ensureError(err))); yield* disconnectAndCancel(); @@ -1211,9 +1205,6 @@ function* handleFlashEV3(action: ReturnType): Generator return [new DataView(reply.payload), undefined]; } - // FIXME: should be called much earlier. - yield* put(didStart()); - const sectorSize = 64 * 1024; // flash memory sector size const maxPayloadSize = 1018; // maximum payload size for EV3 commands @@ -1230,11 +1221,6 @@ function* handleFlashEV3(action: ReturnType): Generator ); if (eraseError) { - yield* put( - alertsShowAlert('alerts', 'unexpectedError', { - error: eraseError, - }), - ); yield* put(alertsHideAlert(firmwareEv3ProgressToastId)); // FIXME: should have a better error reason yield* put(didFailToFinish(FailToFinishReasonType.Unknown, eraseError)); @@ -1248,11 +1234,6 @@ function* handleFlashEV3(action: ReturnType): Generator const [, sendError] = yield* sendCommand(0xf2, new Uint8Array(payload)); if (sendError) { - yield* put( - alertsShowAlert('alerts', 'unexpectedError', { - error: sendError, - }), - ); yield* put(alertsHideAlert(firmwareEv3ProgressToastId)); // FIXME: should have a better error reason yield* put(didFailToFinish(FailToFinishReasonType.Unknown, sendError)); @@ -1298,8 +1279,6 @@ function* handleFlashEV3(action: ReturnType): Generator return; } - yield* put(didFinish()); - yield* cleanup(); yield* put(firmwareDidFlashEV3()); diff --git a/src/utils/index.ts b/src/utils/index.ts index 1b154e1ae..309a34cf3 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// Copyright (c) 2020-2022 The Pybricks Authors +// Copyright (c) 2020-2026 The Pybricks Authors /** * Asserts that an assumption is true. This is used to detect programmer errors @@ -43,7 +43,7 @@ export function hex(n: number, pad: number): string { return `0x${n.toString(16).padStart(pad, '0')}`; } -function isError(err: unknown): err is Error { +export function isError(err: unknown): err is Error { const maybeError = err as Error; return (