Skip to content

Commit

Permalink
feat: Bluetooth handle connection status for knownDevices
Browse files Browse the repository at this point in the history
  • Loading branch information
peter-sanderson committed Feb 26, 2025
1 parent 8d82c24 commit ad15ba6
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ export const BluetoothConnect = ({ onClose, uiMode }: BluetoothConnectProps) =>
const lasUpdatedBoundaryTimestamp =
Date.now() / 1000 - UNPAIRED_DEVICES_LAST_UPDATED_LIMIT_SECONDS;

console.log('allDevices', allDevices);

const devices = allDevices.filter(it => {
const isDeviceAlreadyConnected =
trezorDevices.find(trezorDevice => trezorDevice.bluetoothProps?.id === it.device.id) !==
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,41 @@
import { BluetoothDeviceState, DeviceBluetoothStatusType } from '@suite-common/bluetooth';
import { Button, Row } from '@trezor/components';
import { spacings } from '@trezor/theme';
import { BluetoothDevice as BluetoothDeviceType } from '@trezor/transport-bluetooth';
import { BluetoothDevice } from '@trezor/transport-bluetooth';

import { BluetoothDeviceComponent } from './BluetoothDeviceComponent';

const map: Record<DeviceBluetoothStatusType, string> = {
connecting: 'Connecting',
connected: 'Conencted',
error: 'Error',
pairing: 'Pairing',
paired: 'Paired',
};

type BluetoothDeviceItemProps = {
device: BluetoothDeviceType;
device: BluetoothDeviceState<BluetoothDevice>;
onClick: () => void;
isDisabled?: boolean;
};

export const BluetoothDeviceItem = ({ device, onClick, isDisabled }: BluetoothDeviceItemProps) => (
<Row onClick={onClick} gap={spacings.md} alignItems="stretch">
<BluetoothDeviceComponent device={device} flex="1" />
<Button
variant="primary"
size="small"
margin={{ vertical: spacings.xxs }}
isDisabled={isDisabled}
>
Connect
</Button>
</Row>
);
export const BluetoothDeviceItem = ({ device, onClick }: BluetoothDeviceItemProps) => {
const isDisabled = device.status !== null;
const isLoading = device.status?.type === 'pairing' || device.status?.type === 'connecting';

return (
<Row onClick={isDisabled ? undefined : onClick} gap={spacings.md} alignItems="stretch">
<BluetoothDeviceComponent device={device.device} flex="1" />
{device.status && (
<Button
variant="primary"
size="small"
margin={{ vertical: spacings.xxs }}
isDisabled={isDisabled}
isLoading={isLoading}
>
{map[device.status?.type]}
</Button>
)}
</Row>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ export const BluetoothDeviceList = ({
}: BluetoothDeviceListProps) => (
<Card>
<Column gap={spacings.md} alignItems="stretch">
{deviceList.map(d => (
<BluetoothDeviceItem
key={d.device.id}
device={d.device}
onClick={() => onSelect(d.device.id)}
/>
))}
{deviceList.map(device => (
<BluetoothDeviceItem
key={device.device.id}
device={device}
onClick={() => onSelect(device.device.id)}
/>
))}
{isScanning && <SkeletonDevice />}
</Column>
</Card>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { BluetoothDeviceState } from '@suite-common/bluetooth';
import { ReactNode } from 'react';

import { BluetoothDeviceState, DeviceBluetoothStatusType } from '@suite-common/bluetooth';
import { Card, ElevationContext, Icon, Row, Spinner, Text } from '@trezor/components';
import { spacings } from '@trezor/theme';
import { BluetoothDevice } from '@trezor/transport-bluetooth';
Expand All @@ -8,7 +10,6 @@ import { BluetoothTips } from './BluetoothTips';

const PairedComponent = () => (
<Row gap={spacings.xs} alignItems="center">
{/* Todo: here we shall solve how to continue with Trezor Host Protocol */}
<Icon size="small" name="check"></Icon>
<Text variant="primary">Paired</Text>
</Row>
Expand All @@ -21,17 +22,34 @@ const PairingComponent = () => (
</Row>
);

const ConnectingComponent = () => (
<Row gap={spacings.xs} alignItems="center">
<Spinner size={spacings.sm} />
<Text variant="tertiary">Connecting</Text>
</Row>
);

export type OkComponentProps = {
device: BluetoothDeviceState<BluetoothDevice>;
};

const OkComponent = ({ device }: OkComponentProps) => (
<Row gap={spacings.md} alignItems="center" justifyContent="stretch">
<BluetoothDeviceComponent device={device.device} flex="1" />
const OkComponent = ({ device }: OkComponentProps) => {
const map: Record<DeviceBluetoothStatusType, ReactNode> = {
connecting: <ConnectingComponent />,
connected: null,
error: null,
pairing: <PairingComponent />,
paired: <PairedComponent />,
};

{device?.status?.type === 'connected' ? <PairedComponent /> : <PairingComponent />}
</Row>
);
return (
<Row gap={spacings.md} alignItems="center" justifyContent="stretch">
<BluetoothDeviceComponent device={device.device} flex="1" />

{device?.status?.type !== undefined ? map[device?.status?.type] : null}
</Row>
);
};

export type ErrorComponentProps = {
device: BluetoothDeviceState<BluetoothDevice>;
Expand Down
6 changes: 3 additions & 3 deletions suite-common/bluetooth/src/bluetoothSelectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ export const prepareSelectAllDevices = <T extends BluetoothDeviceCommon>() =>
});

knownDevices.forEach(knownDevice => {
if (!map.has(knownDevice.id)) {
map.set(knownDevice.id, { device: knownDevice, status: null });
}
// All known devices are automatically considered being in 'connecting' state
// underlying code should connect them automatically
map.set(knownDevice.id, { device: knownDevice, status: { type: 'connecting' } });
});

return Array.from(map.values()).sort(
Expand Down

0 comments on commit ad15ba6

Please sign in to comment.