mirror of
https://github.com/pybricks/pybricks-code.git
synced 2026-09-12 17:45:22 +00:00
+24
-1
@@ -4,11 +4,33 @@
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [2.0.0] - 2022-12-20
|
||||
|
||||
### Added
|
||||
- Added Windows DFU USB driver installation instructions ([support#858]).
|
||||
|
||||
### Changed
|
||||
- Clicking empty area of file list focuses the list ([support#856]).
|
||||
- Various text, style and accessibility fixes and improvements.
|
||||
- Updated dependencies.
|
||||
- Updated firmware to v3.2.0:
|
||||
|
||||
#### Changed
|
||||
- Buffered stdout is flushed before ending user program.
|
||||
|
||||
#### Fixed
|
||||
- Fixed SPIKE/MINDSTORMS hubs advertising after disconnect while user program
|
||||
is still running ([support#849]).
|
||||
- Fixed Essential hub hanging on boot when bootloader entered but USB cable
|
||||
not connected ([support#821]).
|
||||
- Fixed button needs debouncing on City/Technic/Essential hubs ([support#716]).
|
||||
- Fixed motor hold drifting away under external input movement ([support#863]).
|
||||
|
||||
[support#716]: https://github.com/pybricks/support/issues/716
|
||||
[support#821]: https://github.com/pybricks/support/issues/821
|
||||
[support#849]: https://github.com/pybricks/support/issues/849
|
||||
[support#863]: https://github.com/pybricks/support/issues/863
|
||||
|
||||
|
||||
[support#856]: https://github.com/pybricks/support/issues/856
|
||||
[support#858]: https://github.com/pybricks/support/issues/858
|
||||
@@ -598,7 +620,8 @@ Prerelease changes are documented at [support#48].
|
||||
|
||||
<!-- links for version headings -->
|
||||
|
||||
[Unreleased]: https://github.com/pybricks/pybricks-code/compare/v2.0.0-rc.1...HEAD
|
||||
[Unreleased]: https://github.com/pybricks/pybricks-code/compare/v2.0.0...HEAD
|
||||
[2.0.0]: https://github.com/pybricks/pybricks-code/compare/v2.0.0-rc.1...v2.0.0
|
||||
[2.0.0-rc.1]: https://github.com/pybricks/pybricks-code/compare/v2.0.0-beta.12...v2.0.0-rc.1
|
||||
[2.0.0-beta.12]: https://github.com/pybricks/pybricks-code/compare/v2.0.0-beta.11...v2.0.0-beta.12
|
||||
[2.0.0-beta.11]: https://github.com/pybricks/pybricks-code/compare/v2.0.0-beta.10...v2.0.0-beta.11
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@pybricks/pybricks-code",
|
||||
"version": "2.0.0-rc.1",
|
||||
"version": "2.0.0",
|
||||
"license": "MIT",
|
||||
"author": "The Pybricks Authors",
|
||||
"repository": {
|
||||
@@ -13,7 +13,7 @@
|
||||
"@blueprintjs/popover2": "^1.10.2",
|
||||
"@blueprintjs/select": "^4.8.12",
|
||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.10",
|
||||
"@pybricks/firmware": "6.4.0",
|
||||
"@pybricks/firmware": "6.5.0",
|
||||
"@pybricks/ide-docs": "2.7.0",
|
||||
"@pybricks/images": "^1.3.0",
|
||||
"@pybricks/jedi": "1.6.0",
|
||||
|
||||
+3
-3
@@ -8,7 +8,7 @@
|
||||
|
||||
import { firmwareVersion } from '@pybricks/firmware';
|
||||
import { Task, buffers, eventChannel } from 'redux-saga';
|
||||
import { satisfies } from 'semver';
|
||||
import { lt, satisfies } from 'semver';
|
||||
import {
|
||||
call,
|
||||
cancel,
|
||||
@@ -223,9 +223,9 @@ function* handleBleConnectPybricks(): Generator {
|
||||
|
||||
// notify user if old firmware
|
||||
if (
|
||||
satisfies(
|
||||
lt(
|
||||
pythonVersionToSemver(firmwareRevision),
|
||||
`<${pythonVersionToSemver(firmwareVersion)}`,
|
||||
pythonVersionToSemver(firmwareVersion),
|
||||
)
|
||||
) {
|
||||
yield* put(alertsShowAlert('ble', 'oldFirmware'));
|
||||
|
||||
@@ -358,57 +358,23 @@ const DfuWindowsDriverInstallDialog: React.VoidFunctionComponent = () => {
|
||||
className="pb-dfu-windows-driver-install-dialog"
|
||||
isOpen={isOpen}
|
||||
onClose={() => dispatch(firmwareDfuWindowsDriverInstallDialogDialogHide())}
|
||||
backButtonProps={{ text: i18n.translate('backButton.label') }}
|
||||
nextButtonProps={{ text: i18n.translate('nextButton.label') }}
|
||||
finalButtonProps={{
|
||||
text: i18n.translate('doneButton.label'),
|
||||
onClick: () =>
|
||||
dispatch(firmwareDfuWindowsDriverInstallDialogDialogHide()),
|
||||
}}
|
||||
>
|
||||
<DialogStep
|
||||
id="1"
|
||||
panel={<Step1 />}
|
||||
nextButtonProps={{ text: i18n.translate('nextButton.label') }}
|
||||
/>
|
||||
<DialogStep
|
||||
id="2"
|
||||
panel={<Step2 hub={hub} />}
|
||||
nextButtonProps={{ text: i18n.translate('nextButton.label') }}
|
||||
/>
|
||||
<DialogStep
|
||||
id="3"
|
||||
panel={<Step3 hub={hub} />}
|
||||
nextButtonProps={{ text: i18n.translate('nextButton.label') }}
|
||||
/>
|
||||
<DialogStep
|
||||
id="4"
|
||||
panel={<Step4 hub={hub} />}
|
||||
nextButtonProps={{ text: i18n.translate('nextButton.label') }}
|
||||
/>
|
||||
<DialogStep
|
||||
id="5"
|
||||
panel={<Step5 hub={hub} />}
|
||||
nextButtonProps={{ text: i18n.translate('nextButton.label') }}
|
||||
/>
|
||||
<DialogStep
|
||||
id="6"
|
||||
panel={<Step6 hub={hub} />}
|
||||
nextButtonProps={{ text: i18n.translate('nextButton.label') }}
|
||||
/>
|
||||
<DialogStep
|
||||
id="7"
|
||||
panel={<Step7 hub={hub} />}
|
||||
nextButtonProps={{ text: i18n.translate('nextButton.label') }}
|
||||
/>
|
||||
<DialogStep
|
||||
id="8"
|
||||
panel={<Step8 />}
|
||||
nextButtonProps={{ text: i18n.translate('nextButton.label') }}
|
||||
/>
|
||||
<DialogStep
|
||||
id="9"
|
||||
panel={<Step9 hub={hub} />}
|
||||
nextButtonProps={{ text: i18n.translate('nextButton.label') }}
|
||||
/>
|
||||
<DialogStep id="1" panel={<Step1 />} />
|
||||
<DialogStep id="2" panel={<Step2 hub={hub} />} />
|
||||
<DialogStep id="3" panel={<Step3 hub={hub} />} />
|
||||
<DialogStep id="4" panel={<Step4 hub={hub} />} />
|
||||
<DialogStep id="5" panel={<Step5 hub={hub} />} />
|
||||
<DialogStep id="6" panel={<Step6 hub={hub} />} />
|
||||
<DialogStep id="7" panel={<Step7 hub={hub} />} />
|
||||
<DialogStep id="8" panel={<Step8 />} />
|
||||
<DialogStep id="9" panel={<Step9 hub={hub} />} />
|
||||
</MultistepDialog>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
{
|
||||
"title": "Windows DFU USB driver installation instructions",
|
||||
"backButton": {
|
||||
"label": "Back"
|
||||
},
|
||||
"nextButton": {
|
||||
"label": "Next"
|
||||
},
|
||||
@@ -18,7 +21,7 @@
|
||||
"properties": "Properties",
|
||||
"listedWithWarning": "If it is listed with a warning sign, right-click it and select {properties}.",
|
||||
"listedWithoutWarning": "If it is listed somewhere else without a warning sign, then the driver is already installed. You may close this window.",
|
||||
"notListed": "If you don't see it at all, make sure the hub is in DFU update mode (see video on the previous page) and try again."
|
||||
"notListed": "If you don't see it at all, make sure that the hub is in DFU update mode and try again. Close this window to watch the video instructions."
|
||||
},
|
||||
"3": {
|
||||
"message": "In the {properties} dialog, click the {updateDriver} button.",
|
||||
|
||||
@@ -461,6 +461,8 @@ export const InstallPybricksDialog: React.VoidFunctionComponent = () => {
|
||||
title={i18n.translate('title')}
|
||||
isOpen={isOpen}
|
||||
onClose={() => dispatch(firmwareInstallPybricksDialogCancel())}
|
||||
backButtonProps={{ text: i18n.translate('backButton.label') }}
|
||||
nextButtonProps={{ text: i18n.translate('nextButton.label') }}
|
||||
finalButtonProps={{
|
||||
text: i18n.translate('flashFirmwareButton.label'),
|
||||
onClick: () =>
|
||||
@@ -482,7 +484,6 @@ export const InstallPybricksDialog: React.VoidFunctionComponent = () => {
|
||||
onCustomFirmwareZip={setCustomFirmwareZip}
|
||||
/>
|
||||
}
|
||||
nextButtonProps={{ text: i18n.translate('nextButton.label') }}
|
||||
/>
|
||||
<DialogStep
|
||||
id="license"
|
||||
@@ -495,7 +496,6 @@ export const InstallPybricksDialog: React.VoidFunctionComponent = () => {
|
||||
onLicenseAcceptedChanged={setLicenseAccepted}
|
||||
/>
|
||||
}
|
||||
backButtonProps={{ text: i18n.translate('backButton.label') }}
|
||||
nextButtonProps={{
|
||||
disabled: !licenseAccepted,
|
||||
text: i18n.translate('nextButton.label'),
|
||||
@@ -510,14 +510,11 @@ export const InstallPybricksDialog: React.VoidFunctionComponent = () => {
|
||||
onChangeHubName={setHubName}
|
||||
/>
|
||||
}
|
||||
backButtonProps={{ text: i18n.translate('backButton.label') }}
|
||||
nextButtonProps={{ text: i18n.translate('nextButton.label') }}
|
||||
/>
|
||||
<DialogStep
|
||||
id="bootloader"
|
||||
title={i18n.translate('bootloaderPanel.title')}
|
||||
panel={<BootloaderModePanel hubType={selectedHubType} />}
|
||||
backButtonProps={{ text: i18n.translate('backButton.label') }}
|
||||
/>
|
||||
</MultistepDialog>
|
||||
);
|
||||
|
||||
@@ -33,9 +33,7 @@ const SelectHubPanel: React.VoidFunctionComponent = () => {
|
||||
<p>
|
||||
{i18n.translate('selectHubPanel.message', {
|
||||
lego: legoRegisteredTrademark,
|
||||
next: (
|
||||
<strong>{i18n.translate('selectHubPanel.nextButton')}</strong>
|
||||
),
|
||||
next: <strong>{i18n.translate('nextButton.label')}</strong>,
|
||||
})}
|
||||
</p>
|
||||
<div className="pb-spacer" />
|
||||
@@ -96,6 +94,8 @@ const RestoreOfficialDialog: React.VoidFunctionComponent = () => {
|
||||
isOpen={isOpen}
|
||||
title={i18n.translate('title', { lego: legoRegisteredTrademark })}
|
||||
onClose={() => dispatch(firmwareRestoreOfficialDialogHide())}
|
||||
backButtonProps={{ text: i18n.translate('backButton.label') }}
|
||||
nextButtonProps={{ text: i18n.translate('nextButton.label') }}
|
||||
finalButtonProps={{
|
||||
text: i18n.translate('doneButton.label'),
|
||||
onClick: () => dispatch(firmwareRestoreOfficialDialogHide()),
|
||||
@@ -105,7 +105,6 @@ const RestoreOfficialDialog: React.VoidFunctionComponent = () => {
|
||||
id="hub"
|
||||
title={i18n.translate('selectHubPanel.title')}
|
||||
panel={<SelectHubPanel />}
|
||||
nextButtonProps={{ text: i18n.translate('selectHubPanel.nextButton') }}
|
||||
/>
|
||||
<DialogStep
|
||||
id="restore"
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
{
|
||||
"title": "Restore official {lego} Firmware",
|
||||
"backButton": {
|
||||
"label": "Back"
|
||||
},
|
||||
"nextButton": {
|
||||
"label": "Next"
|
||||
},
|
||||
"doneButton": {
|
||||
"label": "Done"
|
||||
},
|
||||
"selectHubPanel": {
|
||||
"title": "Select hub",
|
||||
"message": "Select the hub to restore the official {lego} firmware on, then click {next}.",
|
||||
"nextButton": "Next"
|
||||
"message": "Select the hub to restore the official {lego} firmware on, then click {next}."
|
||||
},
|
||||
"restoreFirmwarePanel": {
|
||||
"title": "Restore firmware",
|
||||
|
||||
+1
-6
@@ -193,12 +193,7 @@ const preferredFileFormat: Reducer<FileFormat | null> = (state = null, action) =
|
||||
if (blePybricksServiceDidNotReceiveHubCapabilities.matches(action)) {
|
||||
// HACK: there is not a good way to get the supported MPY ABI version
|
||||
// from a running hub, so we use heuristics on the firmware version.
|
||||
if (
|
||||
semver.satisfies(
|
||||
pythonVersionToSemver(action.firmwareVersion),
|
||||
'>=3.2.0-beta.2',
|
||||
)
|
||||
) {
|
||||
if (semver.lte(pythonVersionToSemver(action.firmwareVersion), '3.2.0-beta.2')) {
|
||||
return FileFormat.Mpy6;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2021 The Pybricks Authors
|
||||
// Copyright (c) 2021-2022 The Pybricks Authors
|
||||
|
||||
import { lt } from 'semver';
|
||||
import { pythonVersionToSemver } from './version';
|
||||
|
||||
describe('pythonVersionToSemver', () => {
|
||||
@@ -14,6 +15,16 @@ describe('pythonVersionToSemver', () => {
|
||||
expect(pythonVersionToSemver(version)).toBe(expected);
|
||||
});
|
||||
|
||||
test.each([
|
||||
['v1.0.0a1', 'v1.0.0b1'],
|
||||
['v1.0.0b1', 'v1.0.0c1'],
|
||||
['v1.0.0c1', 'v1.0.0'],
|
||||
])('%s < %s', (first, second) => {
|
||||
expect(
|
||||
lt(pythonVersionToSemver(first), pythonVersionToSemver(second)),
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
test('invalid version', () => {
|
||||
expect(() => pythonVersionToSemver('not a version')).toThrow();
|
||||
});
|
||||
|
||||
@@ -2359,12 +2359,12 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@pybricks/firmware@npm:6.4.0":
|
||||
version: 6.4.0
|
||||
resolution: "@pybricks/firmware@npm:6.4.0"
|
||||
"@pybricks/firmware@npm:6.5.0":
|
||||
version: 6.5.0
|
||||
resolution: "@pybricks/firmware@npm:6.5.0"
|
||||
dependencies:
|
||||
jszip: ^3.7.1
|
||||
checksum: 47034fc21755840c0740f7c960aead07d5e4f3a020be42456ec3c0eb59af63fdfd5b39cf52155830fd1ea630c4d1adb6d7130978050c12f9d19da5771c9931d0
|
||||
checksum: 1c2518d4e9f8ef2a76be60a30af734b441dbb336b398d7759481f20392e3378e0dbd5927b0f6754f7c29b26e03d3adf78ff2fbb687779fad2f492a3117ce3efa
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -2412,7 +2412,7 @@ __metadata:
|
||||
"@blueprintjs/popover2": ^1.10.2
|
||||
"@blueprintjs/select": ^4.8.12
|
||||
"@pmmmwh/react-refresh-webpack-plugin": ^0.5.10
|
||||
"@pybricks/firmware": 6.4.0
|
||||
"@pybricks/firmware": 6.5.0
|
||||
"@pybricks/ide-docs": 2.7.0
|
||||
"@pybricks/images": ^1.3.0
|
||||
"@pybricks/jedi": 1.6.0
|
||||
|
||||
Reference in New Issue
Block a user