Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extract reducers to common package #17090

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
aa34e30
feat: move reducers into seperate common package, create shared state…
peter-sanderson Feb 19, 2025
c0009aa
feat: implement suite-common bluetooth code into Suite
peter-sanderson Feb 19, 2025
e1e8026
feat: add tests for bluetoothRedcer and devicesSecondTime
peter-sanderson Feb 20, 2025
2ebe1bc
feat: extract functionality and add test for it
peter-sanderson Feb 20, 2025
6a30f1f
fixup! feat: extract functionality and add test for it
peter-sanderson Feb 21, 2025
20fcc71
fixup! feat: move reducers into seperate common package, create share…
peter-sanderson Feb 21, 2025
1d22b88
fixup! feat: extract functionality and add test for it
peter-sanderson Feb 21, 2025
eb34bdb
fixup! feat: implement suite-common bluetooth code into Suite
peter-sanderson Feb 21, 2025
c9d03f1
fixup! feat: move reducers into seperate common package, create share…
peter-sanderson Feb 21, 2025
9dcc1e1
fixup! feat: move reducers into seperate common package, create share…
peter-sanderson Feb 21, 2025
e0b0c76
fixup! feat: implement suite-common bluetooth code into Suite
peter-sanderson Feb 21, 2025
fe0378a
fixup! feat: move reducers into seperate common package, create share…
peter-sanderson Feb 21, 2025
1c10d6c
fixup! feat: implement suite-common bluetooth code into Suite
peter-sanderson Feb 24, 2025
f7c8ca8
feat: Hide Bluetooth devices that are not advertising more then 30 se…
peter-sanderson Feb 24, 2025
ef80901
fix(suite): fix inability to select device (silent return) when one d…
peter-sanderson Feb 24, 2025
1a79397
fixup! feat: implement suite-common bluetooth code into Suite
peter-sanderson Feb 24, 2025
cd31be2
fixup! feat: implement suite-common bluetooth code into Suite
peter-sanderson Feb 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { BluetoothDevice } from '@trezor/transport-bluetooth';

import { remapKnownDevicesForLinux } from '../remapKnownDevicesForLinux';

const nearbyDeviceA: BluetoothDevice = {
id: 'New-Id-A',
data: [],
name: 'Trezor A',
lastUpdatedTimestamp: 1,
address: 'Address-Trezor-A-Staying-Same',
connected: false,
paired: false,
rssi: 0,
};

const nearbyDeviceC: BluetoothDevice = {
id: 'C',
data: [],
name: 'Trezor C',
lastUpdatedTimestamp: 1,
address: 'Address-Trezor-C',
connected: false,
paired: false,
rssi: 0,
};

const knownDeviceB: BluetoothDevice = {
id: 'B',
data: [],
name: 'Trezor A',
lastUpdatedTimestamp: 1,
address: 'Address-Trezor-B',
connected: false,
paired: false,
rssi: 0,
};

const knownDeviceA: BluetoothDevice = {
id: 'Original-Id A',
data: [],
name: 'Trezor B',
lastUpdatedTimestamp: 2,
address: 'Address-Trezor-A-Staying-Same',
connected: false,
paired: false,
rssi: 0,
};

describe(remapKnownDevicesForLinux.name, () => {
it('remaps the changed id of the device, while leaving the others intact', () => {
const result = remapKnownDevicesForLinux({
nearbyDevices: [nearbyDeviceA, nearbyDeviceC],
knownDevices: [knownDeviceA, knownDeviceB],
});

expect(result).toEqual([
{
address: 'Address-Trezor-A-Staying-Same',
connected: false,
data: [],
id: 'New-Id-A',
lastUpdatedTimestamp: 2,
name: 'Trezor B',
paired: false,
rssi: 0,
},
knownDeviceB, // Is kept as it is
]);
});
});
39 changes: 0 additions & 39 deletions packages/suite/src/actions/bluetooth/bluetoothActions.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,15 +1,43 @@
import { BLUETOOTH_PREFIX, bluetoothActions } from '@suite-common/bluetooth';
import { createThunk } from '@suite-common/redux-utils';
import { notificationsActions } from '@suite-common/toast-notifications';
import { bluetoothIpc } from '@trezor/transport-bluetooth';

import { BLUETOOTH_PREFIX } from './bluetoothActions';
type BluetoothConnectDeviceThunkResult = {
success: boolean;
};

type ThunkResponse = ReturnType<typeof bluetoothIpc.connectDevice>;

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

return fulfillWithValue(result);
if (!result.success) {
dispatch(
bluetoothActions.connectDeviceEventAction({
id,
connectionStatus: { type: 'error', error: result.error },
}),
);
dispatch(
notificationsActions.addToast({
type: 'error',
error: result.error,
}),
);
} else {
dispatch(
bluetoothActions.connectDeviceEventAction({
id,
connectionStatus: { type: 'connected' },
}),
);
}

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

import { BLUETOOTH_PREFIX } from './bluetoothActions';

export const bluetoothStartScanningThunk = createThunk<void, void, void>(
`${BLUETOOTH_PREFIX}/bluetoothStartScanningThunk`,
_ => {
(_, { dispatch }) => {
dispatch(bluetoothActions.scanStatusAction({ status: 'running' }));
// This can fail, but if there is an error we already got it from `adapter-event`
// and user is informed about it (bluetooth turned-off, ...)
bluetoothIpc.startScan();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { BLUETOOTH_PREFIX, bluetoothActions } from '@suite-common/bluetooth';
import { createThunk } from '@suite-common/redux-utils';
import { bluetoothIpc } from '@trezor/transport-bluetooth';

import { BLUETOOTH_PREFIX } from './bluetoothActions';

export const bluetoothStopScanningThunk = createThunk<void, void, void>(
`${BLUETOOTH_PREFIX}/bluetoothStopScanningThunk`,
_ => {
(_, { dispatch }) => {
dispatch(bluetoothActions.scanStatusAction({ status: 'idle' }));
// This can fail, but there is nothing we can do about it
bluetoothIpc.stopScan();
},
Expand Down
33 changes: 20 additions & 13 deletions packages/suite/src/actions/bluetooth/initBluetoothThunk.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
import { BLUETOOTH_PREFIX, bluetoothActions, selectKnownDevices } from '@suite-common/bluetooth';
import { createThunk } from '@suite-common/redux-utils/';
import { DeviceConnectionStatus, bluetoothIpc } from '@trezor/transport-bluetooth';
import { BluetoothDevice, DeviceConnectionStatus, bluetoothIpc } from '@trezor/transport-bluetooth';
import { Without } from '@trezor/type-utils';

import {
BLUETOOTH_PREFIX,
bluetoothAdapterEventAction,
bluetoothConnectDeviceEventAction,
bluetoothDeviceListUpdate,
} from './bluetoothActions';
import { remapKnownDevicesForLinux } from './remapKnownDevicesForLinux';
import { selectSuiteFlags } from '../../reducers/suite/suiteReducer';

type DeviceConnectionStatusWithOptionalId = Without<DeviceConnectionStatus, 'id'> & {
Expand All @@ -25,12 +21,23 @@ export const initBluetoothThunk = createThunk<void, void, void>(

bluetoothIpc.on('adapter-event', isPowered => {
console.warn('adapter-event', isPowered);
dispatch(bluetoothAdapterEventAction({ isPowered }));
dispatch(bluetoothActions.adapterEventAction({ isPowered }));
});

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

const knownDevices = selectKnownDevices<BluetoothDevice>(getState());

const remappedKnownDevices = remapKnownDevicesForLinux({
knownDevices,
nearbyDevices,
});

dispatch(
bluetoothActions.knownDevicesUpdateAction({ knownDevices: remappedKnownDevices }),
);
dispatch(bluetoothActions.nearbyDevicesUpdateAction({ nearbyDevices }));
});

bluetoothIpc.on('device-connection-status', connectionStatus => {
Expand All @@ -41,15 +48,15 @@ export const initBluetoothThunk = createThunk<void, void, void>(
delete copyConnectionStatus.id; // So we dont pollute redux store

dispatch(
bluetoothConnectDeviceEventAction({
bluetoothActions.connectDeviceEventAction({
id: connectionStatus.id,
connectionStatus: copyConnectionStatus,
}),
);
});

// TODO: this should be called after trezor/connect init?
const knownDevices = getState().bluetooth.pairedDevices;
const knownDevices = selectKnownDevices<BluetoothDevice>(getState());
await bluetoothIpc.init({ knownDevices });
},
);
27 changes: 27 additions & 0 deletions packages/suite/src/actions/bluetooth/remapKnownDevicesForLinux.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { BluetoothDevice } from '@trezor/transport-bluetooth';

type RemapKnownDevicesForLinuxParams = {
knownDevices: BluetoothDevice[];
nearbyDevices: BluetoothDevice[];
};

/**
* On linux, when bluetooth adapter is turned off/on again, the paired
* devices will get different `id`, but `address` will remain the same.
*
* Therefore, we have to remap the knownDevices to change the `id`.
*/
export const remapKnownDevicesForLinux = ({
knownDevices,
nearbyDevices,
}: RemapKnownDevicesForLinuxParams): BluetoothDevice[] =>
knownDevices.map(knownDevice => {
const nearbyDeviceWithSameAddress = nearbyDevices.find(
nearbyDevice =>
nearbyDevice.address === knownDevice.address && nearbyDevice.id !== knownDevice.id,
);

return nearbyDeviceWithSameAddress
? { ...knownDevice, id: nearbyDeviceWithSameAddress.id }
: knownDevice;
});
4 changes: 2 additions & 2 deletions packages/suite/src/actions/suite/storageActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@ export const saveCoinjoinDebugSettings = () => async (_dispatch: Dispatch, getSt

export const saveKnownDevices = () => async (_dispatch: Dispatch, getState: GetState) => {
if (!(await db.isAccessible())) return;
const { pairedDevices } = getState().bluetooth;
db.addItem('knownDevices', { bluetooth: pairedDevices }, 'devices', true);
const { knownDevices } = getState().bluetooth;
db.addItem('knownDevices', { bluetooth: knownDevices }, 'devices', true);
};

export const saveFormDraft = async (key: string, draft: FieldValues) => {
Expand Down
8 changes: 7 additions & 1 deletion packages/suite/src/actions/wallet/addWalletThunk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,13 @@ export const addWalletThunk = createThunk<
const discovery = selectDiscoveryByDeviceState(getState(), device?.state);
const discoveryStatus = getDiscoveryStatus({ device, discovery });

if (discoveryStatus !== undefined && discoveryStatus.status === 'loading') {
if (
discoveryStatus !== undefined &&
discoveryStatus.status === 'loading' &&
// There are situations where we are in the "state" of discovery, but we want to allow for adding a wallet.
// See: https://github.com/trezor/trezor-suite/issues/17114 for example
discoveryStatus.type === 'discovery'
) {
return;
}

Expand Down
Loading
Loading