Skip to content

Commit

Permalink
firmware/dfuWindowsDriverInstallDialog: move instructions in app
Browse files Browse the repository at this point in the history
This replaces the link for Windows DFU USB driver installation
instructions with a new in-app dialog containing the instructions.

Fixes: pybricks/support#858
  • Loading branch information
dlech committed Dec 19, 2022
1 parent 2dc8ad3 commit 905348a
Show file tree
Hide file tree
Showing 16 changed files with 654 additions and 40 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@

## [Unreleased]

### Added
- Added Windows DFU USB driver installation instructions ([support#858]).

### Changed
- Clicking empty area of file list focuses the list ([support#856]).

[support#856]: https://github.com/pybricks/support/issues/856
[support#858]: https://github.com/pybricks/support/issues/858

## [2.0.0-rc.1] - 2022-12-09

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.10",
"@pybricks/firmware": "6.4.0",
"@pybricks/ide-docs": "2.6.0",
"@pybricks/images": "^1.2.1",
"@pybricks/images": "^1.3.0",
"@pybricks/jedi": "1.6.0",
"@pybricks/mpy-cross-v5": "^2.0.0",
"@pybricks/mpy-cross-v6": "^2.0.0",
Expand Down
2 changes: 2 additions & 0 deletions src/app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import React, { useEffect, useState } from 'react';
import SplitterLayout from 'react-splitter-layout';
import { useLocalStorage, useTernaryDarkMode } from 'usehooks-ts';
import Activities from '../activities/Activities';
import DfuWindowsDriverInstallDialog from '../firmware/dfuWindowsDriverInstallDialog/DfuWindowsDriverInstallDialog';
import { InstallPybricksDialog } from '../firmware/installPybricksDialog/InstallPybricksDialog';
import RestoreOfficialDialog from '../firmware/restoreOfficialDialog/RestoreOfficialDialog';
import { useSettingIsShowDocsEnabled } from '../settings/hooks';
Expand Down Expand Up @@ -248,6 +249,7 @@ const App: React.VFC = () => {
</div>
<StatusBar />
<Tour />
<DfuWindowsDriverInstallDialog />
<InstallPybricksDialog />
<RestoreOfficialDialog />
<SponsorDialog />
Expand Down
3 changes: 0 additions & 3 deletions src/app/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,6 @@ export const pybricksBluetoothTroubleshootingUrl =
export const pybricksUsbDfuTroubleshootingUrl =
'https://github.com/pybricks/support/discussions/688';

export const pybricksUsbDfuWindowsDriverInstallUrl =
'https://github.com/pybricks/support/discussions/688#discussioncomment-3201466';

export const pybricksUsbLinuxUdevRulesUrl =
'https://github.com/pybricks/support/discussions/688#discussioncomment-3239099';

Expand Down
71 changes: 43 additions & 28 deletions src/firmware/bootloaderInstructions/BootloaderInstructions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ import './bootloaderInstructions.scss';
import { Callout, Intent } from '@blueprintjs/core';
import classNames from 'classnames';
import React, { useEffect, useMemo, useRef, useState } from 'react';
import { useDispatch } from 'react-redux';
import {
legoRegisteredTrademark,
pybricksUsbDfuWindowsDriverInstallUrl,
pybricksUsbLinuxUdevRulesUrl,
} from '../../app/constants';
import ExternalLinkIcon from '../../components/ExternalLinkIcon';
import { Hub, hubHasBluetoothButton, hubHasUSB } from '../../components/hubPicker';
import { isLinux, isWindows } from '../../utils/os';
import { firmwareDfuWindowsDriverInstallDialogDialogShow } from '../dfuWindowsDriverInstallDialog/actions';
import cityHubMp4 from './assets/bootloader-cityhub-540.mp4';
import cityHubVtt from './assets/bootloader-cityhub-metadata.vtt';
import essentialHubMp4 from './assets/bootloader-essentialhub-540.mp4';
Expand Down Expand Up @@ -100,6 +101,7 @@ const recoveryMetadataFileMap: ReadonlyMap<Hub, string> = new Map([
const BootloaderInstructions: React.VoidFunctionComponent<
BootloaderInstructionsProps
> = ({ hubType, recovery, flashButtonText }) => {
const dispatch = useDispatch();
const i18n = useI18n();

const { button, light, lightPattern } = useMemo(() => {
Expand Down Expand Up @@ -150,33 +152,6 @@ const BootloaderInstructions: React.VoidFunctionComponent<

return (
<>
{hubHasUSB(hubType) && isLinux() && (
<Callout intent={Intent.WARNING} icon="warning-sign">
{i18n.translate('warning.linux')}{' '}
<a
href={pybricksUsbLinuxUdevRulesUrl}
target="_blank"
rel="noreferrer"
>
{i18n.translate('warning.learnMore')}
</a>
<ExternalLinkIcon />
</Callout>
)}
{hubHasUSB(hubType) && isWindows() && (
<Callout intent={Intent.WARNING} icon="warning-sign">
{i18n.translate('warning.windows')}{' '}
<a
href={pybricksUsbDfuWindowsDriverInstallUrl}
target="_blank"
rel="noreferrer"
>
{i18n.translate('warning.learnMore')}
</a>
<ExternalLinkIcon />
</Callout>
)}

<video
controls
controlsList="nodownload nofullscreen"
Expand Down Expand Up @@ -364,6 +339,46 @@ const BootloaderInstructions: React.VoidFunctionComponent<
) : (
<></>
)}

{hubHasUSB(hubType) && isLinux() && (
<Callout intent={Intent.WARNING} icon="warning-sign">
{i18n.translate('warning.linux.message', {
learnMore: (
<>
<a
href={pybricksUsbLinuxUdevRulesUrl}
target="_blank"
rel="noreferrer"
>
{i18n.translate('warning.linux.learnMore')}
</a>
<ExternalLinkIcon />
</>
),
})}
</Callout>
)}

{hubHasUSB(hubType) && isWindows() && (
<Callout intent={Intent.WARNING} icon="warning-sign">
{i18n.translate('warning.windows.message', {
instructions: (
<a
onMouseDown={(e) => {
e.stopPropagation();
e.preventDefault();

dispatch(
firmwareDfuWindowsDriverInstallDialogDialogShow(),
);
}}
>
{i18n.translate('warning.windows.instructions')}
</a>
),
})}
</Callout>
)}
</>
);
};
Expand Down
11 changes: 8 additions & 3 deletions src/firmware/bootloaderInstructions/translations/en.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
{
"warning": {
"linux": "If you have never used Pybricks with USB on Linux, you will need to configure udev rules before you can install the firmware.",
"windows": " If you have never used Pybricks with USB on Windows, you may need to manually install a USB driver before you can flash the hub firmware.",
"learnMore": "Learn more."
"linux": {
"message": "If you have never used Pybricks with USB on Linux, you will need to configure udev rules before you can install the firmware. {learnMore}",
"learnMore": "Learn more."
},
"windows": {
"message": "If you have never used Pybricks with USB on Windows, you may need to manually install a USB driver before you can connect to the device. {instructions}",
"instructions": "Click for instructions."
}
},
"button": {
"bluetooth": "Bluetooth button",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2022 The Pybricks Authors

import { cleanup } from '@testing-library/react';
import React from 'react';
import { testRender } from '../../../test';
import DfuWindowsDriverInstallDialog from './DfuWindowsDriverInstallDialog';
import { firmwareDfuWindowsDriverInstallDialogDialogHide } from './actions';

afterEach(() => {
cleanup();
jest.resetAllMocks();
localStorage.clear();
sessionStorage.clear();
});

it('should dispatch action when the close button is pressed', async () => {
const [user, dialog, dispatch] = testRender(<DfuWindowsDriverInstallDialog />, {
firmware: { dfuWindowsDriverInstallDialog: { isOpen: true } },
});

await user.click(dialog.getByRole('button', { name: 'Close' }));

expect(dispatch).toHaveBeenCalledWith(
firmwareDfuWindowsDriverInstallDialogDialogHide(),
);
});

it('should navigate when next button is pressed and dispatch action when the done button is pressed', async () => {
const [user, dialog, dispatch] = testRender(<DfuWindowsDriverInstallDialog />, {
firmware: { dfuWindowsDriverInstallDialog: { isOpen: true } },
});

for (let i = 1; i < 9; i++) {
await user.click(dialog.getByRole('button', { name: 'Next' }));
}

await user.click(dialog.getByRole('button', { name: 'Done' }));

expect(dispatch).toHaveBeenCalledWith(
firmwareDfuWindowsDriverInstallDialogDialogHide(),
);
});
Loading

0 comments on commit 905348a

Please sign in to comment.