mirror of
https://github.com/pybricks/pybricks-code.git
synced 2026-07-28 04:08:05 +00:00
firmware/bootloaderInstructions: Refactor.
- Use steps for the connection procedure - Use categories (To do: consider making numbering consecutive) - Show hub bootloader device name explicitly - List official app to use for recovery (make V2/V3 explicit) - Copy edit Also fix the layout (class) of the installation panel to make it consistent with the style of the recovery panel.
This commit is contained in:
committed by
David Lechner
parent
560da418e0
commit
8aa82eee46
@@ -57,6 +57,12 @@ export const pybricksCopyright = 'Copyright (c) 2020-2023 The Pybricks Authors';
|
||||
/** The LEGO name with registered trademark symbol. */
|
||||
export const legoRegisteredTrademark = 'LEGO®';
|
||||
|
||||
/** The LEGO Education SPIKE name with registered trademark symbol. */
|
||||
export const legoEducationSpikeRegisteredTrademark = 'LEGO® Education™ SPIKE™';
|
||||
|
||||
/** The LEGO MINDSTORMS name with registered trademark symbol. */
|
||||
export const legoMindstormsRegisteredTrademark = 'LEGO® MINDSTORMS®';
|
||||
|
||||
// https://www.lego.com/en-us/legal/notices-and-policies/fair-play/
|
||||
/** LEGO "fair play" disclaimer */
|
||||
export const legoDisclaimer =
|
||||
|
||||
@@ -43,8 +43,21 @@ type BootloaderInstructionsProps = {
|
||||
* @default false
|
||||
*/
|
||||
recovery?: boolean;
|
||||
/**
|
||||
* Flash button name that can be referenced in the instructions.
|
||||
*/
|
||||
flashButtonText: string;
|
||||
};
|
||||
|
||||
const bootloaderDeviceNameMap: ReadonlyMap<Hub, string> = new Map([
|
||||
[Hub.City, 'LEGO Bootloader'],
|
||||
[Hub.Essential, 'LEGO Technic Small Hub in DFU Mode'],
|
||||
[Hub.Inventor, 'LEGO Technic Large Hub in DFU Mode'],
|
||||
[Hub.Move, 'LEGO Bootloader'],
|
||||
[Hub.Prime, 'LEGO Technic Large Hub in DFU Mode'],
|
||||
[Hub.Technic, 'LEGO Bootloader'],
|
||||
]);
|
||||
|
||||
const videoFileMap: ReadonlyMap<Hub, string> = new Map([
|
||||
[Hub.City, cityHubMp4],
|
||||
[Hub.Essential, essentialHubMp4],
|
||||
@@ -86,10 +99,10 @@ const recoveryMetadataFileMap: ReadonlyMap<Hub, string> = new Map([
|
||||
*/
|
||||
const BootloaderInstructions: React.VoidFunctionComponent<
|
||||
BootloaderInstructionsProps
|
||||
> = ({ hubType, recovery }) => {
|
||||
> = ({ hubType, recovery, flashButtonText }) => {
|
||||
const i18n = useI18n();
|
||||
|
||||
const { button, light, lightPattern } = useMemo(() => {
|
||||
const { button, light, lightPattern, flashButton } = useMemo(() => {
|
||||
return {
|
||||
button: i18n.translate(
|
||||
hubHasBluetoothButton(hubType) ? 'button.bluetooth' : 'button.power',
|
||||
@@ -102,6 +115,7 @@ const BootloaderInstructions: React.VoidFunctionComponent<
|
||||
? 'lightPattern.bluetooth'
|
||||
: 'lightPattern.status',
|
||||
),
|
||||
flashButton: flashButtonText,
|
||||
};
|
||||
}, [i18n, hubType]);
|
||||
|
||||
@@ -192,38 +206,31 @@ const BootloaderInstructions: React.VoidFunctionComponent<
|
||||
|
||||
<div className="pb-spacer" />
|
||||
|
||||
<p>{i18n.translate('prepare.start')}</p>
|
||||
<p>
|
||||
<strong>{i18n.translate('prepare.start')}</strong>
|
||||
</p>
|
||||
<ol>
|
||||
{hubHasUSB(hubType) ? (
|
||||
<>
|
||||
<li>{i18n.translate('prepare.usb')}</li>
|
||||
<li>{i18n.translate('prepare.turnOff')}</li>
|
||||
</>
|
||||
<li>
|
||||
{i18n.translate(
|
||||
hubHasUSB(hubType) ? 'prepare.usb' : 'prepare.batteries',
|
||||
)}
|
||||
</li>
|
||||
<li>{i18n.translate('prepare.turnOff')}</li>
|
||||
{/* For non-usb recovery, show step about official app */}
|
||||
{recovery && !hubHasUSB(hubType) ? (
|
||||
<li>
|
||||
{i18n.translate('prepare.app', {
|
||||
lego: legoRegisteredTrademark,
|
||||
})}
|
||||
</li>
|
||||
) : (
|
||||
<>
|
||||
{recovery ? (
|
||||
<>
|
||||
<li>
|
||||
{i18n.translate('prepare.batteries')}{' '}
|
||||
{i18n.translate('prepare.turnOff')}
|
||||
</li>
|
||||
<li>
|
||||
{i18n.translate('prepare.app', {
|
||||
lego: legoRegisteredTrademark,
|
||||
})}
|
||||
</li>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<li>{i18n.translate('prepare.batteries')}</li>
|
||||
<li>{i18n.translate('prepare.turnOff')}</li>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
<></>
|
||||
)}
|
||||
</ol>
|
||||
<p>{i18n.translate('step.start')}</p>
|
||||
<ol start={3}>
|
||||
<p>
|
||||
<strong>{i18n.translate('step.start')}</strong>
|
||||
</p>
|
||||
<ol>
|
||||
{/* City hub has power issues and requires disconnecting motors/sensors */}
|
||||
{hubType === Hub.City && (
|
||||
<li
|
||||
@@ -310,6 +317,36 @@ const BootloaderInstructions: React.VoidFunctionComponent<
|
||||
</li>
|
||||
)}
|
||||
</ol>
|
||||
{hubHasUSB(hubType) || (!hubHasUSB(hubType) && !recovery) ? (
|
||||
<>
|
||||
<p>
|
||||
<strong>{i18n.translate('connect.start')}</strong>
|
||||
</p>
|
||||
<ol>
|
||||
<li>
|
||||
{i18n.translate('connect.clickConnectAndFlash', {
|
||||
flashButton: <strong>{flashButton}</strong>,
|
||||
})}
|
||||
</li>
|
||||
<li>
|
||||
{i18n.translate('connect.selectDevice', {
|
||||
deviceName: (
|
||||
<strong>
|
||||
{bootloaderDeviceNameMap.get(hubType)}
|
||||
</strong>
|
||||
),
|
||||
connectButton: (
|
||||
<strong>
|
||||
{i18n.translate('connect.connectButton')}
|
||||
</strong>
|
||||
),
|
||||
})}
|
||||
</li>
|
||||
</ol>
|
||||
</>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"learnMore": "Learn more."
|
||||
},
|
||||
"prepare": {
|
||||
"start": "Now place the hub in update mode. To prepare:",
|
||||
"start": "Preparation:",
|
||||
"batteries": "Make sure the hub has fresh batteries.",
|
||||
"turnOff": "Make sure the hub is turned off.",
|
||||
"usb": "Disconnect the USB cable.",
|
||||
@@ -24,7 +24,7 @@
|
||||
"status": "light purple"
|
||||
},
|
||||
"step": {
|
||||
"start": "Now follow these steps:",
|
||||
"start": "Enter update mode (see video):",
|
||||
"disconnectIo": "Disconnect any device from port A on the hub.",
|
||||
"holdButton": "Press and hold the {button} on the hub.",
|
||||
"connectUsb": "Connect the USB cable.",
|
||||
@@ -32,5 +32,11 @@
|
||||
"waitAppConnect": "The app will automatically connect and start restoring the firmware.",
|
||||
"releaseButton": "Release the {button}.",
|
||||
"keepHolding": "Keep holding the {button}."
|
||||
},
|
||||
"connect": {
|
||||
"start": "Activate the connection:",
|
||||
"clickConnectAndFlash": "Click the {flashButton} button below.",
|
||||
"selectDevice": "In the pop-up dialog, select {deviceName} and click {connectButton}.",
|
||||
"connectButton": "Connect"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -400,15 +400,11 @@ const BootloaderModePanel: React.VoidFunctionComponent<BootloaderModePanelProps>
|
||||
const i18n = useI18n();
|
||||
|
||||
return (
|
||||
<div className={dialogBody}>
|
||||
<BootloaderInstructions hubType={hubType} />
|
||||
<p>
|
||||
{i18n.translate('bootloaderPanel.instruction2', {
|
||||
flashFirmware: (
|
||||
<strong>{i18n.translate('flashFirmwareButton.label')}</strong>
|
||||
),
|
||||
})}
|
||||
</p>
|
||||
<div className={classNames(Classes.DIALOG_BODY, Classes.RUNNING_TEXT)}>
|
||||
<BootloaderInstructions
|
||||
hubType={hubType}
|
||||
flashButtonText={i18n.translate('flashFirmwareButton.label')}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -53,8 +53,7 @@
|
||||
}
|
||||
},
|
||||
"bootloaderPanel": {
|
||||
"title": "Enter update mode",
|
||||
"instruction2": "Then click the {flashFirmware} button below to connect to the hub and flash the firmware."
|
||||
"title": "Install"
|
||||
},
|
||||
"backButton": {
|
||||
"label": "Back"
|
||||
@@ -63,6 +62,6 @@
|
||||
"label": "Next"
|
||||
},
|
||||
"flashFirmwareButton": {
|
||||
"label": "Connect and flash"
|
||||
"label": "Install"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ describe('flashing', () => {
|
||||
|
||||
await user.click(dialog.getByRole('radio', { name: hubName }));
|
||||
await user.click(dialog.getByRole('button', { name: 'Next' }));
|
||||
await user.click(dialog.getByRole('button', { name: 'Flash' }));
|
||||
await user.click(dialog.getByRole('button', { name: 'Restore' }));
|
||||
|
||||
expect(dispatch).toHaveBeenCalledWith(firmwareRestoreOfficialDfu(hub));
|
||||
},
|
||||
|
||||
@@ -11,8 +11,12 @@ import {
|
||||
import classNames from 'classnames';
|
||||
import React from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { legoRegisteredTrademark } from '../../app/constants';
|
||||
import { hubHasUSB } from '../../components/hubPicker';
|
||||
import {
|
||||
legoEducationSpikeRegisteredTrademark,
|
||||
legoMindstormsRegisteredTrademark,
|
||||
legoRegisteredTrademark,
|
||||
} from '../../app/constants';
|
||||
import { Hub, hubHasUSB } from '../../components/hubPicker';
|
||||
import { HubPicker } from '../../components/hubPicker/HubPicker';
|
||||
import { useHubPickerSelectedHub } from '../../components/hubPicker/hooks';
|
||||
import { useSelector } from '../../reducers';
|
||||
@@ -47,18 +51,25 @@ const RestoreFirmwarePanel: React.VoidFunctionComponent = () => {
|
||||
|
||||
return (
|
||||
<div className={classNames(Classes.DIALOG_BODY, Classes.RUNNING_TEXT)}>
|
||||
<BootloaderInstructions hubType={hubType} recovery />
|
||||
<BootloaderInstructions
|
||||
hubType={hubType}
|
||||
recovery
|
||||
flashButtonText={i18n.translate('restoreFirmwarePanel.flashButton')}
|
||||
/>
|
||||
{hubHasUSB(hubType) ? (
|
||||
<>
|
||||
<p>
|
||||
{i18n.translate('restoreFirmwarePanel.instruction2.dfu', {
|
||||
flashFirmware: (
|
||||
<strong>
|
||||
{i18n.translate('restoreFirmwarePanel.flashButton')}
|
||||
</strong>
|
||||
),
|
||||
lego: legoRegisteredTrademark,
|
||||
})}
|
||||
{i18n.translate('restoreFirmwarePanel.instruction2.updateApp', {
|
||||
app:
|
||||
hubType === Hub.Inventor
|
||||
? legoMindstormsRegisteredTrademark
|
||||
: legoEducationSpikeRegisteredTrademark,
|
||||
})}{' '}
|
||||
{hubType !== Hub.Inventor
|
||||
? i18n.translate(
|
||||
'restoreFirmwarePanel.instruction2.updateAppVersion',
|
||||
)
|
||||
: ''}
|
||||
</p>
|
||||
<div className="pb-spacer" />
|
||||
<Button
|
||||
|
||||
@@ -14,8 +14,9 @@
|
||||
"ble": {
|
||||
"message": "When the progress bar is done, the hub will reboot and the app will connect. The official firmware has been restored."
|
||||
},
|
||||
"dfu": "Then click the {flashFirmware} button below to connect to the hub and flash the firmware. After flashing is complete, connect the hub to one of the official {lego} apps and use it to update to the latest official firmware."
|
||||
"updateApp": "Once the recovery is complete, use the {app} app to get the latest official firmware.",
|
||||
"updateAppVersion": "You can use version 2 (legacy) or version 3 to do so."
|
||||
},
|
||||
"flashButton": "Flash"
|
||||
"flashButton": "Restore"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user