Merge pull request #1244 from pybricks/dlech

v2.0.0-beta.6
This commit is contained in:
David Lechner
2022-10-21 16:56:37 -05:00
committed by GitHub
11 changed files with 107 additions and 24 deletions
+54 -1
View File
@@ -4,8 +4,58 @@
## [Unreleased]
## [2.0.0-beta.6] - 2022-10-21
### Added
- Added feature to install custom firmware from file ([pybricks-code#1020]).
- Added support for multi-file programs ([support#189]).
### Changed
- Updated dependencies.
- Updated documentation.
- Updated APIs for code completions.
- Update hub firmware to v3.2.0b4:
### Added
- Added hub shutdown status light indication.
- Added boot and shutdown light matrix animations.
- Added new indication for over-charging battery (blinking green light).
- Added iterator protocol support to `geometry.Matrix` class.
- Added support for multi-file projects ([pybricks-micropython#115]).
- Added new `System.storage()` API ([support#85]).
### Changed
- Battery full indication (green light) comes on earlier ([support#647]).
- User program is saved to non-volatile memory at shutdown on all hubs.
- Restored the `Motor.speed()` method and `DriveBase` equivalent to provide
speed as a numerical derivative of the motor position.
- Starting REPL automatically imports all modules ([support#741]).
- Updated Bluetooth to [Pybricks Profile v1.2.0][pp1.2.0].
- Bluetooth now uses random private address instead of static public address
([support#600]).
### Fixed
- Fixed motors going out of sync when starting program ([support#679]).
- Fixed motor torque signal overflowing under load ([support#729]).
- Fixed city hub turning back on after shutdown ([support#692]).
- Fixed IMU I2C bus lockup on SPIKE hubs ([support#232]).
- Fixed REPL history corrupt after soft reset ([support#699]).
- Fixed "ValueError: incompatible .mpy file" when pressing the button when
there is no program yet ([support#599]).
[pp1.2.0]: https://github.com/pybricks/technical-info/blob/master/pybricks-ble-profile.md#profile-v120
[pybricks-micropython#115]: https://github.com/pybricks/pybricks-micropython/pull/115
[support#85]: https://github.com/pybricks/support/issues/85
[support#232]: https://github.com/pybricks/support/issues/232
[support#599]: https://github.com/pybricks/support/issues/599
[support#600]: https://github.com/pybricks/support/issues/600
[support#647]: https://github.com/pybricks/support/issues/647
[support#679]: https://github.com/pybricks/support/issues/679
[support#692]: https://github.com/pybricks/support/issues/692
[support#699]: https://github.com/pybricks/support/issues/699
[support#729]: https://github.com/pybricks/support/issues/729
[support#741]: https://github.com/pybricks/support/issues/741
### Fixed
- Fixed run button enabled when no file open ([support#691]).
@@ -16,10 +66,12 @@
### Removed
- Removed feature to include custom `main.py` when flashing firmware.
- Removed support for file names containing `-`.
[pybricks-code#938]: https://github.com/pybricks/pybricks-code/issues/938
[pybricks-code#1011]: https://github.com/pybricks/pybricks-code/issues/1011
[pybricks-code#1020]: https://github.com/pybricks/pybricks-code/issues/1020
[support#189]: https://github.com/pybricks/support/issues/189
[support#691]: https://github.com/pybricks/support/issues/691
[support#694]: https://github.com/pybricks/support/issues/694
[support#717]: https://github.com/pybricks/support/issues/717
@@ -371,7 +423,8 @@ Prerelease changes are documented at [support#48].
<!-- links for version headings -->
[Unreleased]: https://github.com/pybricks/pybricks-code/compare/v2.0.0-beta.5...HEAD
[Unreleased]: https://github.com/pybricks/pybricks-code/compare/v2.0.0-beta.6...HEAD
[2.0.0-beta.6]: https://github.com/pybricks/pybricks-code/compare/v2.0.0-beta.5...v2.0.0-beta.6
[2.0.0-beta.5]: https://github.com/pybricks/pybricks-code/compare/v2.0.0-beta.4...v2.0.0-beta.5
[2.0.0-beta.4]: https://github.com/pybricks/pybricks-code/compare/v2.0.0-beta.3...v2.0.0-beta.4
[2.0.0-beta.3]: https://github.com/pybricks/pybricks-code/compare/v2.0.0-beta.2...v2.0.0-beta.3
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@pybricks/pybricks-code",
"version": "2.0.0-beta.5",
"version": "2.0.0-beta.6",
"license": "MIT",
"author": "The Pybricks Authors",
"repository": {
+19 -14
View File
@@ -28,20 +28,25 @@ const UnexpectedErrorAlert: React.VoidFunctionComponent<UnexpectedErrorAlertProp
return (
<>
<p>{i18n.translate('message', { errorMessage: error.message })}</p>
<span>
<Button
aria-labelledby={labelId}
minimal={true}
small={true}
icon={isExpanded ? 'chevron-down' : 'chevron-right'}
onClick={() => setIsExpanded((v) => !v)}
/>
<span id={labelId}>{i18n.translate('technicalInfo')}</span>
</span>
<Collapse isOpen={isExpanded}>
<Pre className="pb-alerts-stack-trace">{error.stack}</Pre>
</Collapse>
<p>{i18n.translate('message')}</p>
<p>{error.message}</p>
{error.stack && (
<>
<span>
<Button
aria-labelledby={labelId}
minimal={true}
small={true}
icon={isExpanded ? 'chevron-down' : 'chevron-right'}
onClick={() => setIsExpanded((v) => !v)}
/>
<span id={labelId}>{i18n.translate('technicalInfo')}</span>
</span>
<Collapse isOpen={isExpanded}>
<Pre className="pb-alerts-stack-trace">{error.stack}</Pre>
</Collapse>
</>
)}
<div>
<ButtonGroup minimal={true} fill={true}>
<Button
+4 -2
View File
@@ -11,14 +11,15 @@ import { AlertActions, AlertDomain, AlertProps, AlertSpecific } from '../alerts'
* @param specific The specific alert for the domain.
* @param props Any additional properties required by this specific alert.
* @param key Optional key to use as unique identifier for toast instead `<domain>.<specific>.<props>`.
* @param update Optional boolean flag to update existing alert instead of replacing it.
*/
export const alertsShowAlert = createAction(
<D extends AlertDomain, S extends AlertSpecific<D>>(
domain: D,
specific: S,
...args: AlertProps<D, S> extends never
? [props?: never]
: [props: AlertProps<D, S>, key?: string]
? [args?: never]
: [props: AlertProps<D, S>, key?: string, update?: boolean]
) => ({
type: 'alerts.action.showAlert',
domain,
@@ -26,6 +27,7 @@ export const alertsShowAlert = createAction(
// HACK: using varargs to allow props and key to be optional
props: args.at(0),
key: args.at(1),
update: args.at(2),
}),
);
+1 -1
View File
@@ -23,7 +23,7 @@ function* handleShowAlert(action: ReturnType<typeof alertsShowAlert>): Generator
// if a toast with the same parameters is already open, close it so we
// can open it again without duplicates.
if (existing.length > 0) {
if (!action.update && existing.length > 0) {
toaster.dismiss(key);
yield* delay(500);
}
+1 -1
View File
@@ -235,7 +235,7 @@ async function runConnectUntil(saga: AsyncSaga, point: ConnectRunPoint): Promise
}
await expect(saga.take()).resolves.toEqual(
blePybricksServiceDidNotReceiveHubCapabilities(pnpId, '3.2.0b4'),
blePybricksServiceDidNotReceiveHubCapabilities(pnpId, '3.2.0b2'),
);
if (point === ConnectRunPoint.DidNotReceiveHubCapabilities) {
+1 -1
View File
@@ -363,7 +363,7 @@ function* handleBleConnectPybricks(): Generator {
);
} else {
yield* put(
blePybricksServiceDidNotReceiveHubCapabilities(pnpId, firmwareVersion),
blePybricksServiceDidNotReceiveHubCapabilities(pnpId, firmwareRevision),
);
}
+18
View File
@@ -140,6 +140,7 @@ describe('flashFirmware', () => {
'flashProgress',
{ action: 'erase', progress: undefined },
'firmware.ble.progress',
true,
),
);
@@ -187,6 +188,7 @@ describe('flashFirmware', () => {
progress: offset / totalFirmwareSize,
},
'firmware.ble.progress',
true,
),
);
@@ -224,6 +226,7 @@ describe('flashFirmware', () => {
progress: 1,
},
'firmware.ble.progress',
true,
),
);
@@ -303,6 +306,7 @@ describe('flashFirmware', () => {
'flashProgress',
{ action: 'erase', progress: undefined },
'firmware.ble.progress',
true,
),
);
@@ -350,6 +354,7 @@ describe('flashFirmware', () => {
progress: offset / totalFirmwareSize,
},
'firmware.ble.progress',
true,
),
);
@@ -387,6 +392,7 @@ describe('flashFirmware', () => {
progress: 1,
},
'firmware.ble.progress',
true,
),
);
@@ -1030,6 +1036,7 @@ describe('flashFirmware', () => {
'flashProgress',
{ action: 'erase', progress: undefined },
'firmware.ble.progress',
true,
),
);
@@ -1142,6 +1149,7 @@ describe('flashFirmware', () => {
'flashProgress',
{ action: 'erase', progress: undefined },
'firmware.ble.progress',
true,
),
);
@@ -1263,6 +1271,7 @@ describe('flashFirmware', () => {
'flashProgress',
{ action: 'erase', progress: undefined },
'firmware.ble.progress',
true,
),
);
@@ -1310,6 +1319,7 @@ describe('flashFirmware', () => {
progress: offset / totalFirmwareSize,
},
'firmware.ble.progress',
true,
),
);
@@ -1437,6 +1447,7 @@ describe('flashFirmware', () => {
'flashProgress',
{ action: 'erase', progress: undefined },
'firmware.ble.progress',
true,
),
);
@@ -1484,6 +1495,7 @@ describe('flashFirmware', () => {
progress: offset / totalFirmwareSize,
},
'firmware.ble.progress',
true,
),
);
@@ -1616,6 +1628,7 @@ describe('flashFirmware', () => {
'flashProgress',
{ action: 'erase', progress: undefined },
'firmware.ble.progress',
true,
),
);
@@ -1664,6 +1677,7 @@ describe('flashFirmware', () => {
progress: offset / totalFirmwareSize,
},
'firmware.ble.progress',
true,
),
);
@@ -1701,6 +1715,7 @@ describe('flashFirmware', () => {
progress: 1,
},
'firmware.ble.progress',
true,
),
);
@@ -2181,6 +2196,7 @@ describe('flashFirmware', () => {
'flashProgress',
{ action: 'erase', progress: undefined },
'firmware.ble.progress',
true,
),
);
@@ -2227,6 +2243,7 @@ describe('flashFirmware', () => {
progress: offset / totalFirmwareSize,
},
'firmware.ble.progress',
true,
),
);
@@ -2263,6 +2280,7 @@ describe('flashFirmware', () => {
progress: 1,
},
'firmware.ble.progress',
true,
),
);
+5
View File
@@ -443,6 +443,7 @@ function* handleFlashFirmware(action: ReturnType<typeof flashFirmware>): Generat
progress: undefined,
},
firmwareBleProgressToastId,
true,
),
);
@@ -508,6 +509,7 @@ function* handleFlashFirmware(action: ReturnType<typeof flashFirmware>): Generat
progress: offset / firmware.length,
},
firmwareBleProgressToastId,
true,
),
);
@@ -593,6 +595,7 @@ function* handleFlashFirmware(action: ReturnType<typeof flashFirmware>): Generat
progress: 1,
},
firmwareBleProgressToastId,
true,
),
);
@@ -632,6 +635,7 @@ function* handleDfuEraseProcess(event: {
progress: event.bytesSent / event.expectedSize,
},
firmwareDfuProgressToastId,
true,
),
);
}
@@ -649,6 +653,7 @@ function* handleDfuWriteProcess(event: {
progress: event.bytesSent / event.expectedSize,
},
firmwareDfuProgressToastId,
true,
),
);
}
+1 -1
View File
@@ -14,7 +14,7 @@ afterEach(() => {
it('should dispatch action when clicked', async () => {
const [user, button, dispatch] = testRender(<ReplButton id="test-repl-button" />, {
hub: { runtime: HubRuntimeState.Idle },
hub: { hasRepl: true, runtime: HubRuntimeState.Idle },
});
await user.click(button.getByRole('button', { name: 'REPL' }));
+2 -2
View File
@@ -13,7 +13,7 @@ import icon from './icon.svg';
type ReplButtonProps = Pick<ActionButtonProps, 'id'>;
const ReplButton: React.VoidFunctionComponent<ReplButtonProps> = ({ id }) => {
const { runtime, useLegacyDownload } = useSelector((s) => s.hub);
const { runtime, useLegacyDownload, hasRepl } = useSelector((s) => s.hub);
const i18n = useI18n();
const dispatch = useDispatch();
@@ -28,7 +28,7 @@ const ReplButton: React.VoidFunctionComponent<ReplButtonProps> = ({ id }) => {
label={i18n.translate('label')}
tooltip={i18n.translate('tooltip')}
icon={icon}
enabled={runtime === HubRuntimeState.Idle}
enabled={hasRepl && runtime === HubRuntimeState.Idle}
onAction={action}
/>
);