mirror of
https://github.com/pybricks/pybricks-code.git
synced 2026-09-14 10:35:11 +00:00
usb: show error message if opening device fails
So far, we've just seen this on Linux when the user doesn't have the correct udev rules installed. We'll have to wait for more user feedback to see what other situations might cause this.
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2025-2026 The Pybricks Authors
|
||||
|
||||
import { Toast } from '@blueprintjs/core';
|
||||
import { act } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { testRender } from '../../../test';
|
||||
import { accessDenied } from './AccessDenied';
|
||||
|
||||
it('should dismiss when close is clicked', async () => {
|
||||
const callback = jest.fn();
|
||||
const toast = accessDenied(callback, undefined as never);
|
||||
|
||||
const [user, message] = testRender(<Toast {...toast} />);
|
||||
|
||||
await act(() => user.click(message.getByRole('button', { name: /close/i })));
|
||||
|
||||
expect(callback).toHaveBeenCalledWith('dismiss');
|
||||
});
|
||||
@@ -0,0 +1,26 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2025-2026 The Pybricks Authors
|
||||
|
||||
import { Intent } from '@blueprintjs/core';
|
||||
import { Error } from '@blueprintjs/icons';
|
||||
import React from 'react';
|
||||
import type { CreateToast } from '../../toasterTypes';
|
||||
import { isLinux } from '../../utils/os';
|
||||
import { useI18n } from './i18n';
|
||||
|
||||
const AccessDenied: React.FunctionComponent = () => {
|
||||
const i18n = useI18n();
|
||||
return (
|
||||
<>
|
||||
<p>{i18n.translate('accessDenied.message')}</p>
|
||||
{isLinux() && <p>{i18n.translate('accessDenied.linuxSuggestion')}</p>}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const accessDenied: CreateToast = (onAction) => ({
|
||||
message: <AccessDenied />,
|
||||
icon: <Error />,
|
||||
intent: Intent.DANGER,
|
||||
onDismiss: () => onAction('dismiss'),
|
||||
});
|
||||
@@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2025-2026 The Pybricks Authors
|
||||
|
||||
import { accessDenied } from './AccessDenied';
|
||||
import { alreadyInUse } from './AlreadyInUse';
|
||||
import { newPybricksProfile } from './NewPybricksProfile';
|
||||
import { noWebUsb } from './NoWebUsb';
|
||||
@@ -8,6 +9,7 @@ import { oldFirmware } from './OldFirmware';
|
||||
|
||||
// gathers all of the alert creation functions for passing up to the top level
|
||||
export default {
|
||||
accessDenied,
|
||||
alreadyInUse,
|
||||
newPybricksProfile,
|
||||
noWebUsb,
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
"suggestion": "Use a supported browser such as Google Chrome or Microsoft Edge.",
|
||||
"action": "More Info"
|
||||
},
|
||||
"accessDenied": {
|
||||
"message": "Access to the USB device was denied.",
|
||||
"linuxSuggestion": "On Linux, ensure that you have the correct udev rules installed."
|
||||
},
|
||||
"alreadyInUse": {
|
||||
"message": "This hub is already in use by another application."
|
||||
},
|
||||
|
||||
+19
-1
@@ -154,7 +154,25 @@ function* handleUsbConnectPybricks(hotPlugDevice?: USBDevice): Generator {
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: show error message to user here
|
||||
// Only show error to the user if they initiated the connection.
|
||||
if (hotPlugDevice === undefined) {
|
||||
if (openErr.name === 'SecurityError') {
|
||||
// Known causes:
|
||||
// - Linux without proper udev rules to allow access to USB devices
|
||||
// - Trying to access a device on a host machine when the USB
|
||||
// device is shared with a VM guest OS.
|
||||
// Other suspected causes:
|
||||
// - Issues with permissions in containerized apps (e.g. Snaps on Ubuntu)
|
||||
yield* put(alertsShowAlert('usb', 'accessDenied'));
|
||||
} else {
|
||||
yield* put(
|
||||
alertsShowAlert('alerts', 'unexpectedError', {
|
||||
error: openErr,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
console.error('Failed to open USB device:', openErr);
|
||||
yield* put(usbDidFailToConnectPybricks());
|
||||
yield* cleanup();
|
||||
|
||||
Reference in New Issue
Block a user