Skip to content

Commit

Permalink
fixup! WIP: design
Browse files Browse the repository at this point in the history
  • Loading branch information
peter-sanderson committed Dec 6, 2024
1 parent 5c99d12 commit e9c83eb
Show file tree
Hide file tree
Showing 9 changed files with 156 additions and 126 deletions.
3 changes: 3 additions & 0 deletions packages/suite-desktop-ui/src/Main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { useDebugLanguageShortcut, useFormattersConfig } from 'src/hooks/suite';
import history from 'src/support/history';
import { ModalContextProvider } from 'src/support/suite/ModalContext';
import { desktopHandshake } from 'src/actions/suite/suiteActions';
import { initBluetoothThunk } from 'src/actions/bluetooth/initBluetoothThunk';
import * as STORAGE from 'src/actions/suite/constants/storageConstants';

import { DesktopUpdater } from './support/DesktopUpdater';
Expand Down Expand Up @@ -134,6 +135,8 @@ export const init = async (container: HTMLElement) => {
TrezorConnect[method] = proxy[method];
});

store.dispatch(initBluetoothThunk());

// finally render whole app
root.render(
<ReduxProvider store={store}>
Expand Down
10 changes: 2 additions & 8 deletions packages/suite/src/actions/bluetooth/bluetoothActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,11 @@ export const bluetoothDeviceListUpdate = createAction(

export const bluetoothConnectDeviceEventAction = createAction(
`${BLUETOOTH_PREFIX}/device-connection-status`,
({ connectionStatus }: { connectionStatus: DeviceBluetoothStatus }) => ({
payload: { connectionStatus },
({ connectionStatus, uuid }: { uuid: string; connectionStatus: DeviceBluetoothStatus }) => ({
payload: { uuid, connectionStatus },
}),
);

export const bluetoothSelectDeviceAction = createAction(
`${BLUETOOTH_PREFIX}/select-device`,
({ uuid }: { uuid: string | undefined }) => ({ payload: { uuid } }),
);

export const bluetoothScanStatusAction = createAction(
`${BLUETOOTH_PREFIX}/scan-status`,
({ status }: { status: BluetoothScanStatus }) => ({ payload: { status } }),
Expand All @@ -40,6 +35,5 @@ export const allBluetoothActions = {
bluetoothAdapterEventAction,
bluetoothDeviceListUpdate,
bluetoothConnectDeviceEventAction,
bluetoothSelectDeviceAction,
bluetoothScanStatusAction,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { createThunk } from '@suite-common/redux-utils';
import { bluetoothManager } from '@trezor/transport-bluetooth';

import { BLUETOOTH_PREFIX } from './bluetoothActions';

type ThunkResponse = ReturnType<typeof bluetoothManager.connectDevice>;

export const bluetoothConnectDeviceThunk = createThunk<ThunkResponse, { uuid: string }, void>(
`${BLUETOOTH_PREFIX}/bluetoothConnectDeviceThunk`,
async ({ uuid }, { fulfillWithValue }) => {
const result = await bluetoothManager.connectDevice(uuid);

return fulfillWithValue(result);
},
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { createThunk } from '@suite-common/redux-utils';
import { bluetoothManager } from '@trezor/transport-bluetooth';

import { BLUETOOTH_PREFIX } from './bluetoothActions';

export const bluetoothStartScanningThunk = createThunk<void, void, void>(
`${BLUETOOTH_PREFIX}/bluetoothStartScanningThunk`,
_ => {
bluetoothManager.startScan();
},
);
11 changes: 11 additions & 0 deletions packages/suite/src/actions/bluetooth/bluetoothStopScanningThunk.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { createThunk } from '@suite-common/redux-utils';
import { bluetoothManager } from '@trezor/transport-bluetooth';

import { BLUETOOTH_PREFIX } from './bluetoothActions';

export const bluetoothStopScanningThunk = createThunk<void, void, void>(
`${BLUETOOTH_PREFIX}/bluetoothStartScanningThunk`,
_ => {
bluetoothManager.stopScan();
},
);
44 changes: 44 additions & 0 deletions packages/suite/src/actions/bluetooth/initBluetoothThunk.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { createThunk } from '@suite-common/redux-utils/';
import { bluetoothManager, DeviceConnectionStatus } from '@trezor/transport-bluetooth';
import { Without } from '@trezor/type-utils';

import {
BLUETOOTH_PREFIX,
bluetoothAdapterEventAction,
bluetoothConnectDeviceEventAction,
bluetoothDeviceListUpdate,
} from './bluetoothActions';

type DeviceConnectionStatusWithOptionalUuid = Without<DeviceConnectionStatus, 'uuid'> & {
uuid?: string;
};

export const initBluetoothThunk = createThunk<void, void, void>(
`${BLUETOOTH_PREFIX}/initBluetoothThunk`,
(_, { dispatch }) => {
bluetoothManager.on('adapter-event', isPowered => {
console.warn('adapter-event', isPowered);
dispatch(bluetoothAdapterEventAction({ isPowered }));
});

bluetoothManager.on('device-list-update', devices => {
console.warn('device-list-update', devices);
dispatch(bluetoothDeviceListUpdate({ devices }));
});

bluetoothManager.on('device-connection-status', connectionStatus => {
console.warn('device-connection-status', connectionStatus);
const copyConnectionStatus: DeviceConnectionStatusWithOptionalUuid = {
...connectionStatus,
};
delete copyConnectionStatus.uuid; // So we dont pollute redux store

dispatch(
bluetoothConnectDeviceEventAction({
uuid: connectionStatus.uuid,
connectionStatus: copyConnectionStatus,
}),
);
});
},
);
71 changes: 25 additions & 46 deletions packages/suite/src/components/suite/bluetooth/BluetoothConnect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import TrezorConnect from '@trezor/connect';
import { Card, Column, ElevationUp } from '@trezor/components';
import { spacings } from '@trezor/theme';
import { notificationsActions } from '@suite-common/toast-notifications';
import { bluetoothManager } from '@trezor/transport-bluetooth';

import { BluetoothNotEnabled } from './errors/BluetoothNotEnabled';
import { BluetoothDeviceList } from './BluetoothDeviceList';
Expand All @@ -15,19 +14,18 @@ import { BluetoothScanFooter } from './BluetoothScanFooter';
import { useDispatch, useSelector } from '../../../hooks/suite';
import { BluetoothSelectedDevice } from './BluetoothSelectedDevice';
import {
bluetoothAdapterEventAction,
bluetoothConnectDeviceEventAction,
bluetoothDeviceListUpdate,
bluetoothScanStatusAction,
bluetoothSelectDeviceAction,
} from '../../../actions/bluetooth/bluetoothActions';
import {
selectBluetoothDeviceList,
selectBluetoothEnabled,
selectBluetoothScanStatus,
selectBluetoothSelectedDevice,
} from '../../../reducers/bluetooth/bluetoothSelectors';
import { BluetoothPairingPin } from './BluetoothPairingPin';
import { bluetoothStartScanningThunk } from '../../../actions/bluetooth/bluetoothStartScanningThunk';
import { bluetoothStopScanningThunk } from '../../../actions/bluetooth/bluetoothStopScanningThunk';
import { bluetoothConnectDeviceThunk } from '../../../actions/bluetooth/bluetoothConnectDeviceThunk';

const SCAN_TIMEOUT = 30_000;

Expand All @@ -40,42 +38,22 @@ type TimerId = ReturnType<typeof setTimeout>; // Todo: TimerId import type after

export const BluetoothConnect = ({ onClose, uiMode }: BluetoothConnectProps) => {
const dispatch = useDispatch();
const [selectedDeviceUuid, setSelectedDeviceUuid] = useState<string | null>(null);
const [scannerTimerId, setScannerTimerId] = useState<TimerId | null>(null);

const isBluetoothEnabled = useSelector(selectBluetoothEnabled);
const scanStatus = useSelector(selectBluetoothScanStatus);
const selectedDevice = useSelector(selectBluetoothSelectedDevice);
const deviceList = useSelector(selectBluetoothDeviceList);
const devices = Object.values(deviceList);

// Todo: move this to some Singleton component to synchronize the bluetoothManager with Redux State
// Todo: or move to action in the same manner as TrezorConnect.init() is initialized
// See: package/suite/services
useEffect(() => {
bluetoothManager.on('adapter-event', isPowered => {
console.warn('adapter-event', isPowered);
dispatch(bluetoothAdapterEventAction({ isPowered }));
});

bluetoothManager.on('device-list-update', devices => {
console.warn('device-list-update', devices);
dispatch(bluetoothDeviceListUpdate({ devices }));
});

bluetoothManager.on('device-connection-status', connectionStatus => {
console.warn('device-connection-status', connectionStatus);
dispatch(bluetoothConnectDeviceEventAction({ connectionStatus }));
});
const selectedDevice =
selectedDeviceUuid !== null ? deviceList[selectedDeviceUuid] ?? null : null;

// Todo: this shall not be on top-level, this shall be called onClick on the connect button
bluetoothManager.startScan();
useEffect(() => {
dispatch(bluetoothStartScanningThunk());

return () => {
bluetoothManager.removeAllListeners('adapter-event');
bluetoothManager.removeAllListeners('device-list-update');
bluetoothManager.removeAllListeners('device-connection-status');

// Todo: move this to action and run on close or something
bluetoothManager.stopScan();
dispatch(bluetoothStopScanningThunk());
};
}, [dispatch]);

Expand All @@ -95,7 +73,7 @@ export const BluetoothConnect = ({ onClose, uiMode }: BluetoothConnectProps) =>
}, [dispatch]);

const onReScanClick = () => {
dispatch(bluetoothSelectDeviceAction({ uuid: undefined }));
setSelectedDeviceUuid(null);
dispatch(bluetoothScanStatusAction({ status: 'running' }));

clearScamTimer();
Expand All @@ -106,15 +84,15 @@ export const BluetoothConnect = ({ onClose, uiMode }: BluetoothConnectProps) =>
};

const onSelect = async (uuid: string) => {
dispatch(bluetoothSelectDeviceAction({ uuid }));
setSelectedDeviceUuid(uuid);

// Todo move this to action and call this in thunk
const result = await bluetoothManager.connectDevice(uuid);
const result = await dispatch(bluetoothConnectDeviceThunk({ uuid })).unwrap();

if (!result.success) {
dispatch(
bluetoothConnectDeviceEventAction({
connectionStatus: { type: 'error', uuid, error: result.error },
uuid,
connectionStatus: { type: 'error', error: result.error },
}),
);
dispatch(
Expand All @@ -128,7 +106,8 @@ export const BluetoothConnect = ({ onClose, uiMode }: BluetoothConnectProps) =>

dispatch(
bluetoothConnectDeviceEventAction({
connectionStatus: { type: 'connected', uuid },
uuid,
connectionStatus: { type: 'connected' },
}),
);

Expand Down Expand Up @@ -156,19 +135,19 @@ export const BluetoothConnect = ({ onClose, uiMode }: BluetoothConnectProps) =>

// This is fake, we scan for devices all the time
const isScanning = scanStatus !== 'done';
const scanFailed = deviceList.length === 0 && scanStatus === 'done';
const scanFailed = devices.length === 0 && scanStatus === 'done';

const handlePairingCancel = () => {
dispatch(bluetoothSelectDeviceAction({ uuid: undefined }));
setSelectedDeviceUuid(null);
onReScanClick();
};

if (selectedDevice !== undefined && selectedDevice.status.type !== 'pairing') {
if (selectedDevice !== null && selectedDevice.status.type !== 'pairing') {
return <BluetoothSelectedDevice device={selectedDevice} onReScanClick={onReScanClick} />;
}

if (
selectedDevice !== undefined &&
selectedDevice !== null &&
selectedDevice.status.type === 'pairing' &&
(selectedDevice.status.pin?.length ?? 0) > 0
) {
Expand All @@ -187,7 +166,7 @@ export const BluetoothConnect = ({ onClose, uiMode }: BluetoothConnectProps) =>
<BluetoothDeviceList
isDisabled={selectedDevice !== undefined}
onSelect={onSelect}
deviceList={deviceList}
deviceList={devices}
isScanning={isScanning}
/>
);
Expand All @@ -203,7 +182,7 @@ export const BluetoothConnect = ({ onClose, uiMode }: BluetoothConnectProps) =>
<BluetoothScanHeader
isScanning={isScanning}
onClose={onClose}
numberOfDevices={deviceList.length}
numberOfDevices={devices.length}
/>

{/* Here we need to do +1 in elevation because of custom design on the welcome screen */}
Expand All @@ -212,7 +191,7 @@ export const BluetoothConnect = ({ onClose, uiMode }: BluetoothConnectProps) =>
{uiMode === 'card' && (
<BluetoothScanFooter
onReScanClick={onReScanClick}
numberOfDevices={deviceList.length}
numberOfDevices={devices.length}
scanStatus={scanStatus}
/>
)}
Expand All @@ -225,7 +204,7 @@ export const BluetoothConnect = ({ onClose, uiMode }: BluetoothConnectProps) =>
<ElevationUp>
<BluetoothScanFooter
onReScanClick={onReScanClick}
numberOfDevices={deviceList.length}
numberOfDevices={devices.length}
scanStatus={scanStatus}
/>
</ElevationUp>
Expand Down
Loading

0 comments on commit e9c83eb

Please sign in to comment.