Skip to content

Commit

Permalink
WIP: design
Browse files Browse the repository at this point in the history
feat: implement Bluetooth Onboarding UI

feat: different 'Not the Trezor you are looking for' UI

feat: implement Bluetooth Onboarding UI 2

feat: implement Bluetooth Onboarding UI

feat: different 'Not the Trezor you are looking for' UI

feat: implement Bluetooth Onboarding UI 2

feat: use CollapsibleBox component in Bluetooth UI

fix: after rebase

enable BT onboarding

WIP: transport name

breaking change

aftr rebase
  • Loading branch information
peter-sanderson authored and szymonlesisz committed Dec 5, 2024
1 parent b443734 commit ef44c9d
Show file tree
Hide file tree
Showing 28 changed files with 1,065 additions and 50 deletions.
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';

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
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,12 @@ export const RotateDeviceImage = ({

const isDeviceImageRotating =
deviceModel &&
[DeviceModelInternal.T2B1, DeviceModelInternal.T3B1, DeviceModelInternal.T3T1].includes(
deviceModel,
);
[
DeviceModelInternal.T2B1,
DeviceModelInternal.T3B1,
DeviceModelInternal.T3T1,
DeviceModelInternal.T3W1,
].includes(deviceModel);

return (
<>
Expand Down
45 changes: 45 additions & 0 deletions packages/suite/src/actions/bluetooth/bluetoothActions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { createAction } from '@reduxjs/toolkit';

import { BluetoothDevice } from '@trezor/transport-bluetooth';

import {
BluetoothScanStatus,
DeviceBluetoothStatus,
} from '../../reducers/bluetooth/bluetoothReducer';

export const BLUETOOTH_PREFIX = '@suite/bluetooth';

export const bluetoothAdapterEventAction = createAction(
`${BLUETOOTH_PREFIX}/adapter-event`,
({ isPowered }: { isPowered: boolean }) => ({ payload: { isPowered } }),
);

export const bluetoothDeviceListUpdate = createAction(
`${BLUETOOTH_PREFIX}/device-list-update`,
({ devices }: { devices: BluetoothDevice[] }) => ({ payload: { devices } }),
);

export const bluetoothConnectDeviceEventAction = createAction(
`${BLUETOOTH_PREFIX}/device-connection-status`,
({ connectionStatus }: { connectionStatus: DeviceBluetoothStatus }) => ({
payload: { 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 } }),
);

export const allBluetoothActions = {
bluetoothAdapterEventAction,
bluetoothDeviceListUpdate,
bluetoothConnectDeviceEventAction,
bluetoothSelectDeviceAction,
bluetoothScanStatusAction,
};
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 @@ -10,9 +12,15 @@ import {

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

export const DeviceConnect = ({ isWebUsbTransport }: DeviceConnectProps) => {
export const DeviceConnect = ({
isWebUsbTransport,
onBluetoothClick,
isBluetooth,
}: DeviceConnectProps) => {
const items = isWebUsbTransport
? [
TROUBLESHOOTING_TIP_UDEV,
Expand All @@ -32,7 +40,23 @@ export const DeviceConnect = ({ isWebUsbTransport }: DeviceConnectProps) => {
<TroubleshootingTips
label={<Translation id="TR_STILL_DONT_SEE_YOUR_TREZOR" />}
items={items}
cta={isWebUsbTransport ? <WebUsbButton data-testid="@webusb-button" /> : undefined}
cta={
// eslint-disable-next-line no-nested-ternary
isBluetooth ? (
<Button
variant="tertiary"
size="tiny"
onClick={e => {
e.stopPropagation();
onBluetoothClick();
}}
>
Connect Safe 7 via bluetooth
</Button>
) : isWebUsbTransport ? (
<WebUsbButton data-testid="@webusb-button" />
) : undefined
}
data-testid="@connect-device-prompt/no-device-detected"
/>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
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';
import { useDispatch, useSelector } from 'src/hooks/suite';
import { selectIsWebUsb, selectPrerequisite } from 'src/reducers/suite/suiteReducer';
import {
selectIsWebUsb,
selectIsBluetooth,
selectPrerequisite,
} from 'src/reducers/suite/suiteReducer';
import { goto } from 'src/actions/suite/routerActions';

import { Transport } from './Transport';
Expand All @@ -26,6 +30,7 @@ import { DeviceUpdateRequired } from './DeviceUpdateRequired';
import { DeviceDisconnectRequired } from './DeviceDisconnectRequired';
import { MultiShareBackupInProgress } from './MultiShareBackupInProgress';
import { DeviceUsedElsewhere } from './DeviceUsedElsewhere';
import { BluetoothConnect } from '../bluetooth/BluetoothConnect';

const Wrapper = styled.div`
display: flex;
Expand All @@ -48,11 +53,15 @@ 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;
const isWebUsbTransport = useSelector(selectIsWebUsb);
const isBluetooth = useSelector(selectIsBluetooth);
const prerequisite = useSelector(selectPrerequisite);

const TipComponent = useMemo(
Expand All @@ -63,7 +72,13 @@ export const PrerequisitesGuide = ({ allowSwitchDevice }: PrerequisitesGuideProp
case 'device-disconnect-required':
return <DeviceDisconnectRequired />;
case 'device-disconnected':
return <DeviceConnect isWebUsbTransport={isWebUsbTransport} />;
return (
<DeviceConnect
isWebUsbTransport={isWebUsbTransport}
isBluetooth={isBluetooth}
onBluetoothClick={() => setIsBluetoothConnectOpen(true)}
/>
);
case 'device-unacquired':
return <DeviceAcquire />;
case 'device-used-elsewhere':
Expand Down Expand Up @@ -91,38 +106,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}
/>

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

0 comments on commit ef44c9d

Please sign in to comment.