mirror of
https://github.com/pybricks/pybricks-code.git
synced 2026-09-14 10:35:11 +00:00
+54
-1
@@ -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
@@ -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": {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -363,7 +363,7 @@ function* handleBleConnectPybricks(): Generator {
|
||||
);
|
||||
} else {
|
||||
yield* put(
|
||||
blePybricksServiceDidNotReceiveHubCapabilities(pnpId, firmwareVersion),
|
||||
blePybricksServiceDidNotReceiveHubCapabilities(pnpId, firmwareRevision),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
@@ -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,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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' }));
|
||||
|
||||
@@ -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}
|
||||
/>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user