Since we now have periodic status messages, we don't need to do anything
to get into a known state.
This caused unexpected behavior when connecting to a hub that is already
connected in a second window.
The Loaded state is not used anywhere else, so we can replace it with
the Unknown state. Then we can make all other command-in-progress
states (start repl/stop user program) the same as download and run.
When the command completes, the hub is in an unknown state until a
status message is received. The Disconnected states overrides all other
states.
- Add check for repl start command success/fail.
- Show error message on fail.
- Rename start repl action.
- Add new did start/did fail to start repl actions.
- Change terminal saga to use did start repl action to focus terminal.
- Add more tests.
WebBluetooth generally uses DomException with name NetworkError to mean
that Bluetooth is disconnected, so we can use that to provide a helpful
error message.
When disconnect is requested, we should not longer allow interacting
with the hub, so we say the runtime state is unknown until it is
confirmed to be disconnected.
Fixes: https://github.com/pybricks/support/issues/1021
Some user events trigger react dom changes. These need to be wrapped in
act() to avoid a warning printed to the console. To be save, we wrap
all instances.
This makes the required changes needed to make the editor components
and sagas lazy-load to improve the time before the first render of the
app.
This is done by making sure we only import types from the monaco editor
module anywhere other than the saga and the component modules and using
React.lazy to lazy-load the component and start the sagas.
This cuts the main bundle time to less than 1/2 so load time should be
over twice as fast now.
This adds support to the BLE Pybricks Profile v1.2.0. This includes a
new method to download and run programs and a new file format for the
user program.
Code for the old download and run is kept for backwards compatibility.
However, the PnP ID characteristic is no longer optional, so the
minimum Pybricks Profile is now v1.1.0.
This makes the code a bit shorter by not having to use `props.` all of
the time. Also make everything VoidFunctionComponent while we are
touching this.
This uses the real rootReducer to populate the initial state in the test
AsyncSaga. This way we don't have to populate default values. Since it
isn't used often, we can omit the parameter and just call the updateState()
method after creating the object if modifications are needed.
This removes use of the pseudo-internal toString() function and also
removes extraneous uses of ReturnType<>. Also, a new when() method
is added to simplify additional uses.
The pattern we were using for actions required actions to be defined in
three places, an enum member containing the type string, an type
definition and a function. This combines all three of these into one by
using a helper function based on the ideas from [1].
[1]: https://phryneas.de/redux-typescript-no-discriminating-union