Skip to content

Commit

Permalink
feat: implement Bluetooth Onboarding UI
Browse files Browse the repository at this point in the history
  • Loading branch information
peter-sanderson committed Nov 25, 2024
1 parent 8108e12 commit 95f7171
Show file tree
Hide file tree
Showing 20 changed files with 574 additions and 285 deletions.
2 changes: 1 addition & 1 deletion packages/components/src/components/NewModal/types.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { UIVariant, UISize, UIHorizontalAlignment, UIVerticalAlignment } from '../../config/types';

export const newModalVariants = ['primary', 'warning', 'destructive'] as const;
export const newModalVariants = ['primary', 'warning', 'destructive', 'info'] as const;
export type NewModalVariant = Extract<UIVariant, (typeof newModalVariants)[number]>;

export const newModalSizes = ['huge', 'large', 'medium', 'small', 'tiny'] as const;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import styled, { css } from 'styled-components';

import { Elevation, borders, mapElevationToBackground } from '@trezor/theme';
import { Elevation, borders, mapElevationToBackground, nextElevation } from '@trezor/theme';

Check failure on line 3 in packages/components/src/components/skeletons/SkeletonRectangle.tsx

View workflow job for this annotation

GitHub Actions / Linting and formatting

'nextElevation' is defined but never used. Allowed unused vars must match /^_/u

import { SkeletonBaseProps } from './types';
import { getValue, shimmerEffect } from './utils';
Expand All @@ -18,7 +18,12 @@ const StyledSkeletonRectangle = styled.div<
>`
width: ${({ $width }) => getValue($width) ?? '80px'};
height: ${({ $height }) => getValue($height) ?? '20px'};
background: ${({ $background, ...props }) => $background ?? mapElevationToBackground(props)};
background: ${({ $background, ...props }) =>
$background ??
mapElevationToBackground({
theme: props.theme,
$elevation: props.$elevation,
})};
border-radius: ${({ $borderRadius }) => getValue($borderRadius) ?? borders.radii.xs};
background-size: 200%;
Expand Down
4 changes: 2 additions & 2 deletions packages/suite-desktop-api/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
Status,
BridgeSettings,
TorSettings,
TraySettings,
TraySettings, ElectronBluetoothDevice
} from './messages';

// Event messages from renderer to main process
Expand Down Expand Up @@ -75,7 +75,7 @@ export interface RendererChannels {
'handshake/event': HandshakeEvent;
'bluetooth/event': any;
'bluetooth/adapter-event': boolean;
'bluetooth/select-device-event': { uuid: string; name: string }[];
'bluetooth/select-device-event': ElectronBluetoothDevice[];
'bluetooth/pair-device-event': { paired: boolean; pin: string };
'bluetooth/connect-device-event': any;
}
Expand Down
1 change: 1 addition & 0 deletions packages/suite-desktop-api/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export type {
BootstrapTorEvent,
TorStatusEvent,
HandshakeTorModule,
ElectronBluetoothDevice,
} from './messages';

export { TorStatus } from './enums';
9 changes: 9 additions & 0 deletions packages/suite-desktop-api/src/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,12 @@ export type InvokeResult<Payload = undefined> =
ExtractUndefined<Payload> extends undefined
? { success: true; payload?: Payload } | { success: false; error: string; code?: string }
: { success: true; payload: Payload } | { success: false; error: string; code?: string };

export interface ElectronBluetoothDevice {
uuid: string;
name: string;
paired: boolean;
connected: boolean;
timestamp: number;
rssi: number;
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Button } from '@trezor/components';

import { Translation, TroubleshootingTips, WebUsbButton } from 'src/components/suite';
import {
TROUBLESHOOTING_TIP_BRIDGE_STATUS,
Expand All @@ -7,16 +9,18 @@ import {
TROUBLESHOOTING_TIP_DIFFERENT_COMPUTER,
TROUBLESHOOTING_TIP_UDEV,
} from 'src/components/suite/troubleshooting/tips';
import { Button } from '@trezor/components';
import { openModal } from '../../../actions/suite/modalActions';
import { useDispatch } from '../../../hooks/suite';

interface DeviceConnectProps {
isWebUsbTransport: boolean;
isBluetooth: boolean;
onBluetoothClick: () => void;
}

export const DeviceConnect = ({ isWebUsbTransport, isBluetooth }: DeviceConnectProps) => {
export const DeviceConnect = ({
isWebUsbTransport,
onBluetoothClick,
isBluetooth,
}: DeviceConnectProps) => {
const items = isWebUsbTransport
? [
TROUBLESHOOTING_TIP_UDEV,
Expand All @@ -32,8 +36,6 @@ export const DeviceConnect = ({ isWebUsbTransport, isBluetooth }: DeviceConnectP
TROUBLESHOOTING_TIP_DIFFERENT_COMPUTER,
];

const dispatch = useDispatch();

return (
<TroubleshootingTips
label={<Translation id="TR_STILL_DONT_SEE_YOUR_TREZOR" />}
Expand All @@ -46,7 +48,8 @@ export const DeviceConnect = ({ isWebUsbTransport, isBluetooth }: DeviceConnectP
size="tiny"
onClick={e => {
e.stopPropagation();
dispatch(openModal({ type: 'select-bluetooth-device' }));
onBluetoothClick();
// dispatch(openModal({ type: 'select-bluetooth-device' }));
}}
>
Connect Safe 7 via bluetooth
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { useMemo } from 'react';
import { useMemo, useState } from 'react';

import styled from 'styled-components';
import { motion } from 'framer-motion';

import { getStatus, deviceNeedsAttention } from '@suite-common/suite-utils';
import { Button, motionEasing } from '@trezor/components';
import { Button, ElevationContext, ElevationDown, motionEasing } from '@trezor/components';
import { selectDevices, selectDevice } from '@suite-common/wallet-core';

import { ConnectDevicePrompt, Translation } from 'src/components/suite';
Expand All @@ -26,6 +26,7 @@ import { DeviceNoFirmware } from './DeviceNoFirmware';
import { DeviceUpdateRequired } from './DeviceUpdateRequired';
import { DeviceDisconnectRequired } from './DeviceDisconnectRequired';
import { MultiShareBackupInProgress } from './MultiShareBackupInProgress';
import { BluetoothConnect } from '../bluetooth/BluetoothConnect';

const Wrapper = styled.div`
display: flex;
Expand All @@ -48,7 +49,10 @@ interface PrerequisitesGuideProps {
}

export const PrerequisitesGuide = ({ allowSwitchDevice }: PrerequisitesGuideProps) => {
const [isBluetoothConnectOpen, setIsBluetoothConnectOpen] = useState(false);

const dispatch = useDispatch();

const device = useSelector(selectDevice);
const devices = useSelector(selectDevices);
const connectedDevicesCount = devices.filter(d => d.connected === true).length;
Expand All @@ -70,6 +74,7 @@ export const PrerequisitesGuide = ({ allowSwitchDevice }: PrerequisitesGuideProp
<DeviceConnect
isWebUsbTransport={isWebUsbTransport}
isBluetooth={isBluetooth}
onBluetoothClick={() => setIsBluetoothConnectOpen(true)}
/>
);
case 'device-unacquired':
Expand Down Expand Up @@ -97,38 +102,49 @@ export const PrerequisitesGuide = ({ allowSwitchDevice }: PrerequisitesGuideProp
return <></>;
}
},
[prerequisite, isWebUsbTransport, device],
[prerequisite, isWebUsbTransport, isBluetooth, device],
);

const handleSwitchDeviceClick = () =>
dispatch(goto('suite-switch-device', { params: { cancelable: true } }));

return (
<Wrapper>
<ConnectDevicePrompt
connected={!!device}
showWarning={
!!(device && deviceNeedsAttention(getStatus(device))) ||
prerequisite === 'transport-bridge'
}
prerequisite={prerequisite}
/>

{allowSwitchDevice && connectedDevicesCount > 1 && (
<ButtonWrapper>
<Button variant="tertiary" onClick={handleSwitchDeviceClick}>
<Translation id="TR_SWITCH_DEVICE" />
</Button>
</ButtonWrapper>
{isBluetoothConnectOpen ? (
<ElevationContext baseElevation={-1}>
{/* Here we need to draw the inner card with elevation -1 (custom design) */}
<ElevationDown>
<BluetoothConnect onClose={() => setIsBluetoothConnectOpen(false)} />
</ElevationDown>
</ElevationContext>
) : (
<>
<ConnectDevicePrompt
connected={!!device}
showWarning={
!!(device && deviceNeedsAttention(getStatus(device))) ||
prerequisite === 'transport-bridge'
}
prerequisite={prerequisite}
/>

{allowSwitchDevice && connectedDevicesCount > 1 && (
<ButtonWrapper>
<Button variant="tertiary" onClick={handleSwitchDeviceClick}>
<Translation id="TR_SWITCH_DEVICE" />
</Button>
</ButtonWrapper>
)}

<TipsContainer
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 0.6, duration: 0.5, ease: motionEasing.enter }}
>
<TipComponent />
</TipsContainer>
</>
)}

<TipsContainer
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 0.6, duration: 0.5, ease: motionEasing.enter }}
>
<TipComponent />
</TipsContainer>
</Wrapper>
);
};
Loading

0 comments on commit 95f7171

Please sign in to comment.