From af8a31d50cc17c042b480e86273098db0109b110 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 20 Jul 2022 14:25:40 -0500 Subject: [PATCH] firmware: add select picker for selecting custom main.py --- package.json | 1 + src/firmware/actions.ts | 8 +-- .../InstallPybricksDialog.tsx | 66 +++++++++++++++++-- src/firmware/installPybricksDialog/actions.ts | 7 +- src/firmware/installPybricksDialog/i18n.ts | 6 +- .../translations/en.json | 8 ++- src/firmware/sagas.test.ts | 42 ++++++------ src/firmware/sagas.ts | 33 ++++++++-- src/index.scss | 4 ++ yarn.lock | 16 +++++ 10 files changed, 150 insertions(+), 41 deletions(-) diff --git a/package.json b/package.json index 66510ebb..9814a362 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "@babel/core": "^7.18.6", "@blueprintjs/core": "^4.5.0", "@blueprintjs/popover2": "^1.4.2", + "@blueprintjs/select": "^4.4.2", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.7", "@pybricks/firmware": "4.16.1", "@pybricks/ide-docs": "2.2.0", diff --git a/src/firmware/actions.ts b/src/firmware/actions.ts index 793db68c..6526d0fc 100644 --- a/src/firmware/actions.ts +++ b/src/firmware/actions.ts @@ -120,15 +120,15 @@ export type FailToFinishReason = /** * Creates a new action to flash firmware to a hub. * @param data The firmware zip file data or `null` to get firmware later. - * @param flashCurrentProgram If true, flash the current program from the editor, - * otherwise use the program from firmware.zip. + * @param customProgram If defined, flash the path of a program from file storage, + * otherwise use the main.py program from firmware.zip. * @param hubName A custom hub name or an empty string to use the default name. */ export const flashFirmware = createAction( - (data: ArrayBuffer | null, flashCurrentProgram: boolean, hubName: string) => ({ + (data: ArrayBuffer | null, customProgram: string | undefined, hubName: string) => ({ type: 'flashFirmware.action.flashFirmware', data, - flashCurrentProgram, + customProgram, hubName, }), ); diff --git a/src/firmware/installPybricksDialog/InstallPybricksDialog.tsx b/src/firmware/installPybricksDialog/InstallPybricksDialog.tsx index 8b581277..3dd1a85c 100644 --- a/src/firmware/installPybricksDialog/InstallPybricksDialog.tsx +++ b/src/firmware/installPybricksDialog/InstallPybricksDialog.tsx @@ -13,12 +13,14 @@ import { Icon, InputGroup, Intent, + MenuItem, MultistepDialog, NonIdealState, Spinner, Switch, } from '@blueprintjs/core'; import { Classes as Classes2, Popover2 } from '@blueprintjs/popover2'; +import { Select2 } from '@blueprintjs/select'; import classNames from 'classnames'; import React, { useMemo, useState } from 'react'; import { useDispatch } from 'react-redux'; @@ -31,6 +33,8 @@ import { hubHasUSB, } from '../../components/hubPicker'; import { HubPicker } from '../../components/hubPicker/HubPicker'; +import { FileMetadata } from '../../fileStorage'; +import { useFileStorageMetadata } from '../../fileStorage/hooks'; import { useSelector } from '../../reducers'; import { firmwareInstallPybricksDialogAccept, @@ -176,19 +180,24 @@ type SelectOptionsPanelProps = { hubType: Hub; hubName: string; includeProgram: boolean; + selectedIncludeFile: FileMetadata | undefined; onChangeHubName(hubName: string): void; onChangeIncludeProgram(includeProgram: boolean): void; + onChangeSelectedIncludeFile(selectedIncludeFile: FileMetadata | undefined): void; }; const ConfigureOptionsPanel: React.VoidFunctionComponent = ({ hubType, hubName, includeProgram, + selectedIncludeFile, onChangeHubName, onChangeIncludeProgram, + onChangeSelectedIncludeFile, }) => { const i18n = useI18n(); const isHubNameValid = validateHubName(hubName); + const files = useFileStorageMetadata(); return (
@@ -198,7 +207,6 @@ const ConfigureOptionsPanel: React.VoidFunctionComponent onChangeHubName(e.currentTarget.value)} onMouseOver={(e) => e.preventDefault()} @@ -234,8 +242,9 @@ const ConfigureOptionsPanel: React.VoidFunctionComponent main.py }, )} checked={includeProgram} onChange={(e) => @@ -244,12 +253,54 @@ const ConfigureOptionsPanel: React.VoidFunctionComponent + ( + + )} + noResults={ + + } + filterable={false} + popoverProps={{ minimal: true }} + disabled={!includeProgram} + onItemSelect={onChangeSelectedIncludeFile} + > +