diff --git a/packages/suite/src/components/suite/bluetooth/BluetoothConnect.tsx b/packages/suite/src/components/suite/bluetooth/BluetoothConnect.tsx index ff59e97ca66..ff08adfd987 100644 --- a/packages/suite/src/components/suite/bluetooth/BluetoothConnect.tsx +++ b/packages/suite/src/components/suite/bluetooth/BluetoothConnect.tsx @@ -159,7 +159,13 @@ export const BluetoothConnect = ({ onClose, uiMode }: BluetoothConnectProps) => } if (selectedDevice !== undefined) { - return ; + return ( + + ); } const content = scanFailed ? ( diff --git a/packages/suite/src/components/suite/bluetooth/BluetoothDeviceComponent.tsx b/packages/suite/src/components/suite/bluetooth/BluetoothDeviceComponent.tsx index 37fa30d4605..aaf0db000f3 100644 --- a/packages/suite/src/components/suite/bluetooth/BluetoothDeviceComponent.tsx +++ b/packages/suite/src/components/suite/bluetooth/BluetoothDeviceComponent.tsx @@ -36,7 +36,9 @@ export const BluetoothDeviceComponent = ({ device, flex, margin }: BluetoothDevi Trezor Safe 7 - + +
{device.macAddress}
+
{colorName} diff --git a/packages/suite/src/components/suite/bluetooth/BluetoothDeviceItem.tsx b/packages/suite/src/components/suite/bluetooth/BluetoothDeviceItem.tsx index 4e8898bb0e1..c2d7182f6b0 100644 --- a/packages/suite/src/components/suite/bluetooth/BluetoothDeviceItem.tsx +++ b/packages/suite/src/components/suite/bluetooth/BluetoothDeviceItem.tsx @@ -7,7 +7,7 @@ import { BluetoothDeviceComponent } from './BluetoothDeviceComponent'; const map: Record = { connecting: 'Connecting', - connected: 'Conencted', + connected: 'Connected', error: 'Error', pairing: 'Pairing', paired: 'Paired', @@ -23,19 +23,17 @@ export const BluetoothDeviceItem = ({ device, onClick }: BluetoothDeviceItemProp const isLoading = device.status?.type === 'pairing' || device.status?.type === 'connecting'; return ( - + - {device.status && ( - - )} + ); }; diff --git a/packages/suite/src/components/suite/bluetooth/BluetoothSelectedDevice.tsx b/packages/suite/src/components/suite/bluetooth/BluetoothSelectedDevice.tsx index f90feda3d96..ddb6750baf1 100644 --- a/packages/suite/src/components/suite/bluetooth/BluetoothSelectedDevice.tsx +++ b/packages/suite/src/components/suite/bluetooth/BluetoothSelectedDevice.tsx @@ -1,7 +1,16 @@ import { ReactNode } from 'react'; import { BluetoothDeviceState, DeviceBluetoothStatusType } from '@suite-common/bluetooth'; -import { Card, ElevationContext, Icon, Row, Spinner, Text } from '@trezor/components'; +import { + Button, + Card, + Column, + ElevationContext, + Icon, + Row, + Spinner, + Text, +} from '@trezor/components'; import { spacings } from '@trezor/theme'; import { BluetoothDevice } from '@trezor/transport-bluetooth'; @@ -9,31 +18,32 @@ import { BluetoothDeviceComponent } from './BluetoothDeviceComponent'; import { BluetoothTips } from './BluetoothTips'; const PairedComponent = () => ( - + Paired ); const PairingComponent = () => ( - - + + Pairing ); const ConnectingComponent = () => ( - - + + Connecting ); export type OkComponentProps = { device: BluetoothDeviceState; + onCancel: () => void; }; -const OkComponent = ({ device }: OkComponentProps) => { +const OkComponent = ({ device, onCancel }: OkComponentProps) => { const map: Record = { connecting: , connected: null, @@ -46,7 +56,12 @@ const OkComponent = ({ device }: OkComponentProps) => { - {device?.status?.type !== undefined ? map[device?.status?.type] : null} + + {device?.status?.type !== undefined ? map[device?.status?.type] : null} + + ); }; @@ -67,18 +82,20 @@ const ErrorComponent = ({ device, onReScanClick }: ErrorComponentProps) => { export type BluetoothSelectedDeviceProps = { device: BluetoothDeviceState; onReScanClick: () => void; + onCancel: () => void; }; export const BluetoothSelectedDevice = ({ device, onReScanClick, + onCancel, }: BluetoothSelectedDeviceProps) => ( {device?.status?.type === 'error' ? ( ) : ( - + )} diff --git a/suite-common/bluetooth/src/bluetoothSelectors.ts b/suite-common/bluetooth/src/bluetoothSelectors.ts index abb8ccb2c12..7dce9bb2382 100644 --- a/suite-common/bluetooth/src/bluetoothSelectors.ts +++ b/suite-common/bluetooth/src/bluetoothSelectors.ts @@ -27,13 +27,18 @@ export const prepareSelectAllDevices = () => (nearbyDevices, knownDevices) => { const map = new Map>(); - nearbyDevices.forEach(nearbyDevice => { - map.set(nearbyDevice.device.id, nearbyDevice); - }); + nearbyDevices + // Devices with error status should be displayed in the list, as it + // won't be possible to connect to them ever again. User has to start + // pairing again, which would produce a device with new id. + .filter(nearbyDevice => nearbyDevice.status?.type !== 'error') + .forEach(nearbyDevice => { + map.set(nearbyDevice.device.id, nearbyDevice); + }); knownDevices.forEach(knownDevice => { // All known devices are automatically considered being in 'connecting' state - // underlying code should connect them automatically + // underlying code should connect them automatically. map.set(knownDevice.id, { device: knownDevice, status: { type: 'connecting' } }); }); diff --git a/suite-common/bluetooth/tests/bluetoothSelectors.test.ts b/suite-common/bluetooth/tests/bluetoothSelectors.test.ts index 375dddd75c4..5b92143e353 100644 --- a/suite-common/bluetooth/tests/bluetoothSelectors.test.ts +++ b/suite-common/bluetooth/tests/bluetoothSelectors.test.ts @@ -26,21 +26,35 @@ const deviceB: BluetoothDeviceCommon = { lastUpdatedTimestamp: 2, }; +const pairingDeviceStateC: BluetoothDeviceState = { + device: { + id: 'C', + data: [], + name: 'Trezor C', + lastUpdatedTimestamp: 3, + }, + status: { type: 'pairing' }, +}; + describe('bluetoothSelectors', () => { - it('selects knownDevices and nearbyDevices in one list fot the UI', () => { + it('selects knownDevices and nearbyDevices in one list fot the UI, all known devices are', () => { const selectAllDevices = prepareSelectAllDevices(); const state: WithBluetoothState = { bluetooth: { ...initialState, - nearbyDevices: [pairingDeviceStateA], + nearbyDevices: [pairingDeviceStateA, pairingDeviceStateC], knownDevices: [pairingDeviceStateA.device, deviceB], }, }; const devices = selectAllDevices(state); - expect(devices).toEqual([{ device: deviceB, status: null }, pairingDeviceStateA]); + expect(devices).toEqual([ + pairingDeviceStateC, + { device: deviceB, status: { type: 'connecting' } }, + { device: pairingDeviceStateA.device, status: { type: 'connecting' } }, // overrides to 'connecting' + ]); const devicesSecondTime = selectAllDevices(state); expect(devices === devicesSecondTime).toBe(true); // Asserts that `reselect` memoization works