Skip to content

Commit 4fcb82e

Browse files
committed
bootloaderInstructions: add recovery variant
For official firmware recovery, we have separate videos for non-USB hubs. Closes: pybricks/support#728
1 parent 0f871c6 commit 4fcb82e

12 files changed

Lines changed: 113 additions & 37 deletions

src/app/constants.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,6 @@ export const pybricksUsbDfuWindowsDriverInstallUrl =
5151
export const pybricksUsbLinuxUdevRulesUrl =
5252
'https://github.com/pybricks/support/discussions/688#discussioncomment-3239099';
5353

54-
export const pybricksBleFirmwareRestoreVideoUrl =
55-
'https://pybricks.com/install/technic-boost-city/#restoring-the-original-firmware';
56-
5754
/** Pybricks copyright statement. */
5855
export const pybricksCopyright = 'Copyright (c) 2020-2023 The Pybricks Authors';
5956

src/firmware/bootloaderInstructions/BootloaderInstructions.tsx

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { Callout, Intent } from '@blueprintjs/core';
66
import classNames from 'classnames';
77
import React, { useEffect, useMemo, useRef, useState } from 'react';
88
import {
9+
legoRegisteredTrademark,
910
pybricksUsbDfuWindowsDriverInstallUrl,
1011
pybricksUsbLinuxUdevRulesUrl,
1112
} from '../../app/constants';
@@ -24,10 +25,24 @@ import primeHubMp4 from './assets/bootloader-primehub-540.mp4';
2425
import primeHubVtt from './assets/bootloader-primehub-metadata.vtt';
2526
import technicHubMp4 from './assets/bootloader-technichub-540.mp4';
2627
import technicHubVtt from './assets/bootloader-technichub-metadata.vtt';
28+
import cityHubRecoveryMp4 from './assets/recover-cityhub-540.mp4';
29+
import cityHubRecoveryVtt from './assets/recover-cityhub-metadata.vtt';
30+
import moveHubRecoveryMp4 from './assets/recover-movehub-540.mp4';
31+
import moveHubRecoveryVtt from './assets/recover-movehub-metadata.vtt';
32+
import technicHubRecoveryMp4 from './assets/recover-technichub-540.mp4';
33+
import technicHubRecoveryVtt from './assets/recover-technichub-metadata.vtt';
2734
import { useI18n } from './i18n';
2835

2936
type BootloaderInstructionsProps = {
37+
/**
38+
* The instructions and video will be customized for this hub.
39+
*/
3040
hubType: Hub;
41+
/**
42+
* If true, show official firmware recovery video and steps for supported hubs.
43+
* @default false
44+
*/
45+
recovery?: boolean;
3146
};
3247

3348
const videoFileMap: ReadonlyMap<Hub, string> = new Map([
@@ -48,13 +63,30 @@ const metadataFileMap: ReadonlyMap<Hub, string> = new Map([
4863
[Hub.Technic, technicHubVtt],
4964
]);
5065

66+
const recoveryVideoFileMap: ReadonlyMap<Hub, string> = new Map([
67+
[Hub.City, cityHubRecoveryMp4],
68+
[Hub.Essential, essentialHubMp4],
69+
[Hub.Inventor, inventorHubMp4],
70+
[Hub.Move, moveHubRecoveryMp4],
71+
[Hub.Prime, primeHubMp4],
72+
[Hub.Technic, technicHubRecoveryMp4],
73+
]);
74+
75+
const recoveryMetadataFileMap: ReadonlyMap<Hub, string> = new Map([
76+
[Hub.City, cityHubRecoveryVtt],
77+
[Hub.Essential, essentialHubVtt],
78+
[Hub.Inventor, inventorHubVtt],
79+
[Hub.Move, moveHubRecoveryVtt],
80+
[Hub.Prime, primeHubVtt],
81+
[Hub.Technic, technicHubRecoveryVtt],
82+
]);
5183
/**
5284
* Provides customized instructions on how to enter bootloader mode based
5385
* on the hub type.
5486
*/
5587
const BootloaderInstructions: React.VoidFunctionComponent<
5688
BootloaderInstructionsProps
57-
> = ({ hubType }) => {
89+
> = ({ hubType, recovery }) => {
5890
const i18n = useI18n();
5991

6092
const { button, light, lightPattern } = useMemo(() => {
@@ -139,10 +171,21 @@ const BootloaderInstructions: React.VoidFunctionComponent<
139171
disablePictureInPicture
140172
className="pb-bootloader-video"
141173
>
142-
<source src={videoFileMap.get(hubType)} type="video/mp4" />
174+
<source
175+
src={
176+
recovery
177+
? recoveryVideoFileMap.get(hubType)
178+
: videoFileMap.get(hubType)
179+
}
180+
type="video/mp4"
181+
/>
143182
<track
144183
kind="metadata"
145-
src={metadataFileMap.get(hubType)}
184+
src={
185+
recovery
186+
? recoveryMetadataFileMap.get(hubType)
187+
: metadataFileMap.get(hubType)
188+
}
146189
ref={metadataTrackRef}
147190
/>
148191
</video>
@@ -153,6 +196,10 @@ const BootloaderInstructions: React.VoidFunctionComponent<
153196
{i18n.translate('instruction', {
154197
startPoweredOff: hubHasUSB(hubType)
155198
? i18n.translate('startPoweredOff.usb')
199+
: recovery
200+
? i18n.translate('startPoweredOff.recovery', {
201+
lego: legoRegisteredTrademark,
202+
})
156203
: i18n.translate('startPoweredOff.default'),
157204
})}
158205
</p>
@@ -210,8 +257,18 @@ const BootloaderInstructions: React.VoidFunctionComponent<
210257
</li>
211258
)}
212259

260+
{recovery && !hubHasUSB(hubType) && (
261+
<li
262+
className={classNames(
263+
activeStep === 'wait-app-connect' && 'pb-active-step',
264+
)}
265+
>
266+
{i18n.translate('step.waitAppConnect')}
267+
</li>
268+
)}
269+
213270
{/* hubs with USB will keep the power on, but other hubs won't */}
214-
{hubHasUSB(hubType) ? (
271+
{recovery || hubHasUSB(hubType) ? (
215272
<li
216273
className={classNames(
217274
activeStep === 'release-button' && 'pb-active-step',
Binary file not shown.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
WEBVTT
2+
3+
disconnect-io
4+
00:00.100 --> 00:07.000
5+
6+
hold-button
7+
00:07.000 --> 00:11.000
8+
9+
wait-for-light
10+
00:11.000 --> 00:19.000
11+
12+
wait-app-connect
13+
00:19.000 --> 00:25.000
14+
15+
release-button
16+
00:25.000 --> 00:28.000
Binary file not shown.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
WEBVTT
2+
3+
hold-button
4+
00:00.100 --> 00:05.000
5+
6+
wait-for-light
7+
00:05.000 --> 00:11.000
8+
9+
wait-app-connect
10+
00:11.000 --> 00:15.000
11+
12+
release-button
13+
00:15.000 --> 00:18.000
Binary file not shown.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
WEBVTT
2+
3+
hold-button
4+
00:05.000 --> 00:08.000
5+
6+
wait-for-light
7+
00:08.000 --> 00:14.000
8+
9+
wait-app-connect
10+
00:14.000 --> 00:21.000
11+
12+
release-button
13+
00:21.000 --> 00:24.000

src/firmware/bootloaderInstructions/bootloaderInstructions.scss

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@
88

99
.pb-bootloader-video {
1010
width: 90%;
11-
align-self: center;
11+
display: block;
12+
margin: 0 auto;
1213
}

src/firmware/bootloaderInstructions/translations/en.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
"instruction": "To flash the firmware, the hub must be placed in bootloader mode. {startPoweredOff}, then follow the instructions below:",
88
"startPoweredOff": {
99
"default": "Start with the hub powered off",
10-
"usb": "Start with the hub powered off and the USB cable disconnected"
10+
"usb": "Start with the hub powered off and the USB cable disconnected",
11+
"recovery": "Start with the hub powered off and the {lego} PoweredUp app opened to any 'Create' program"
1112
},
1213
"button": {
1314
"bluetooth": "Bluetooth button",
@@ -26,7 +27,8 @@
2627
"holdButton": "Press and hold the {button} on the hub.",
2728
"connectUsb": "Connect the USB cable.",
2829
"waitForLight": "Keep holding the {button} and wait for the {light} to start flashing {lightPattern}. This takes about 5 seconds.",
29-
"releaseButton": "Release the {button}",
30+
"waitAppConnect": "The app will automatically connect and start flashing the firmware.",
31+
"releaseButton": "Release the {button}.",
3032
"keepHolding": "Keep holding the {button}."
3133
}
3234
}

0 commit comments

Comments
 (0)