Skip to content

Commit

Permalink
feat(suite-native): new device switcher
Browse files Browse the repository at this point in the history
  • Loading branch information
vytick committed May 15, 2024
1 parent 192128a commit 3cdd926
Show file tree
Hide file tree
Showing 38 changed files with 1,116 additions and 440 deletions.
4 changes: 0 additions & 4 deletions suite-common/icons/assets/icons/linkChain.svg

This file was deleted.

3 changes: 0 additions & 3 deletions suite-common/icons/assets/icons/linkChainBroken.svg

This file was deleted.

2 changes: 0 additions & 2 deletions suite-common/icons/src/icons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,6 @@ export const icons = {
label: require('../assets/icons/label.svg'),
lifebuoy: require('../assets/icons/lifebuoy.svg'),
link: require('../assets/icons/link.svg'),
linkChain: require('../assets/icons/linkChain.svg'),
linkChainBroken: require('../assets/icons/linkChainBroken.svg'),
lock: require('../assets/icons/lock.svg'),
minus: require('../assets/icons/minus.svg'),
minusCircle: require('../assets/icons/minusCircle.svg'),
Expand Down
14 changes: 14 additions & 0 deletions suite-common/suite-utils/src/device.ts
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,20 @@ export const getPhysicalDeviceUniqueIds = (devices: Device[]) =>
export const getPhysicalDeviceCount = (devices: Device[]) =>
getPhysicalDeviceUniqueIds(devices).length;

export const getSortedDevicesWithoutInstances = (
devices: TrezorDevice[],
excludedDeviceId?: string | null,
) =>
getDeviceInstancesGroupedByDeviceId(devices)
.flatMap(group => group[0])
.filter(d => d?.id !== excludedDeviceId && d?.id)
.sort((a, b) => {
if (!a.connected) return -1;
if (!b.connected) return 1;

return 0;
});

export const parseFirmwareChangelog = (release?: FirmwareRelease) => {
if (!release?.changelog?.length || !release) {
return null;
Expand Down
21 changes: 20 additions & 1 deletion suite-common/wallet-core/src/device/deviceReducer.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { memoize } from 'proxy-memoize';

import * as deviceUtils from '@suite-common/suite-utils';
import { getStatus } from '@suite-common/suite-utils';
import { getDeviceInstances, getStatus } from '@suite-common/suite-utils';
import { Device, Features, UI } from '@trezor/connect';
import { getFirmwareVersion, getFirmwareVersionArray } from '@trezor/device-utils';
import { Network, networks } from '@suite-common/wallet-config';
Expand Down Expand Up @@ -858,3 +858,22 @@ export const selectDeviceState = (state: DeviceRootState) => {

return device?.state ?? null;
};

export const selectDeviceInstances = memoize((state: DeviceRootState) => {
const device = selectDevice(state);

if (!device) {
return [];
}

const allDevices = selectDevices(state);

return getDeviceInstances(device, allDevices);
});

export const selectInstacelessUnselectedDevices = memoize((state: DeviceRootState) => {
const device = selectDevice(state);
const allDevices = selectDevices(state);

return deviceUtils.getSortedDevicesWithoutInstances(allDevices, device?.id);
});
9 changes: 5 additions & 4 deletions suite-native/atoms/src/TextDivider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,17 @@ type TextDividerProps = {

const separatorStyle = prepareNativeStyle<{ horizontalMargin?: number }>(
(utils, { horizontalMargin }) => ({
borderColor: utils.colors.borderElevation0,
borderWidth: utils.borders.widths.small,
backgroundColor: utils.colors.borderElevation0,
height: utils.borders.widths.small,
flex: 1,
// We want the separator to be full width, but we need to offset it by the parent padding
marginHorizontal: typeof horizontalMargin === 'number' ? -horizontalMargin : 0,
}),
);

const separatorTitleStyle = prepareNativeStyle(_ => ({
const separatorTitleStyle = prepareNativeStyle(utils => ({
paddingHorizontal: 12,
paddingVertical: utils.spacings.extraSmall,
}));

export const TextDivider = ({ title, horizontalMargin = 0 }: TextDividerProps) => {
Expand All @@ -31,7 +32,7 @@ export const TextDivider = ({ title, horizontalMargin = 0 }: TextDividerProps) =
<HStack alignItems="center">
<Box style={applyStyle(separatorStyle, { horizontalMargin })} />
<Box style={applyStyle(separatorTitleStyle)}>
<Text>
<Text variant="label">
<Translation id={title} />
</Text>
</Box>
Expand Down
1 change: 1 addition & 0 deletions suite-native/device-manager/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@reduxjs/toolkit": "1.9.5",
"@suite-common/icons": "workspace:*",
"@suite-common/suite-types": "workspace:*",
"@suite-common/suite-utils": "workspace:*",
"@suite-common/wallet-core": "workspace:*",
"@suite-native/analytics": "workspace:*",
"@suite-native/atoms": "workspace:*",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
import { useDispatch, useSelector } from 'react-redux';

import { Button } from '@suite-native/atoms';
import { Translation } from '@suite-native/intl';
import { createDeviceInstance, selectDevice } from '@suite-common/wallet-core';
import { Text } from '@suite-native/atoms';
import { prepareNativeStyle, useNativeStyles } from '@trezor/styles';
import { Icon } from '@suite-common/icons';

import { useDeviceManager } from '../hooks/useDeviceManager';
import { DeviceAction } from './DeviceAction';

const textStyle = prepareNativeStyle(_ => ({
flex: 1,
}));

export const AddHiddenWalletButton = () => {
const { applyStyle } = useNativeStyles();
const dispatch = useDispatch();

const device = useSelector(selectDevice);
Expand All @@ -21,8 +29,15 @@ export const AddHiddenWalletButton = () => {
};

return (
<Button colorScheme="tertiaryElevation1" onPress={handleAddHiddenWallet}>
<Translation id="deviceManager.deviceButtons.addHiddenWallet" />
</Button>
<DeviceAction
testID="@device-manager/passphrase/add"
onPress={handleAddHiddenWallet}
flex={1}
>
<Text variant="hint" style={applyStyle(textStyle)}>
<Translation id="deviceManager.deviceButtons.addHiddenWallet" />
</Text>
<Icon name="chevronRight" color="iconDefault" size="mediumLarge" />
</DeviceAction>
);
};
60 changes: 60 additions & 0 deletions suite-native/device-manager/src/components/DeviceAction.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { ReactNode } from 'react';
import { Pressable } from 'react-native';

import { HStack } from '@suite-native/atoms';
import { prepareNativeStyle, useNativeStyles } from '@trezor/styles';

type DeviceActionProps = {
testID: string;
onPress: () => void;
children: ReactNode;
flex?: number;
showAsFullWidth?: boolean;
};

const contentStyle = prepareNativeStyle(utils => ({
paddingHorizontal: utils.spacings.medium,
paddingVertical: 12,
alignItems: 'center',
height: 44,
gap: utils.spacings.small,
backgroundColor: utils.colors.backgroundSurfaceElevation1,
borderWidth: utils.borders.widths.small,
borderRadius: 12,
borderColor: utils.colors.borderElevation1,
}));

const pressableStyle = prepareNativeStyle<{ showAsFullWidth: boolean; flex: number | undefined }>(
(_, { showAsFullWidth, flex }) => {
return {
flex,
extend: {
condition: showAsFullWidth,
style: {
flex: 1,
justifyContent: 'center',
},
},
};
},
);

export const DeviceAction = ({
testID,
onPress,
children,
flex,
showAsFullWidth = false,
}: DeviceActionProps) => {
const { applyStyle } = useNativeStyles();

return (
<Pressable
onPress={onPress}
testID={testID}
style={applyStyle(pressableStyle, { showAsFullWidth, flex })}
>
<HStack style={applyStyle(contentStyle)}>{children}</HStack>
</Pressable>
);
};

This file was deleted.

68 changes: 68 additions & 0 deletions suite-native/device-manager/src/components/DeviceInfoButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { useSelector } from 'react-redux';

import { useNavigation } from '@react-navigation/native';

import { analytics, EventType } from '@suite-native/analytics';
import { HStack, Text } from '@suite-native/atoms';
import { selectDevice } from '@suite-common/wallet-core';
import { Translation } from '@suite-native/intl';
import {
RootStackParamList,
RootStackRoutes,
StackToStackCompositeNavigationProps,
} from '@suite-native/navigation';
import { Icon } from '@suite-common/icons';
import { prepareNativeStyle, useNativeStyles } from '@trezor/styles';

import { useDeviceManager } from '../hooks/useDeviceManager';
import { DeviceAction } from './DeviceAction';

type NavigationProp = StackToStackCompositeNavigationProps<
RootStackParamList,
RootStackRoutes.AppTabs,
RootStackParamList
>;

type DeviceInfoButtonProps = {
showAsFullWidth: boolean;
};

const contentStyle = prepareNativeStyle<{ showAsFullWidth: boolean }>((_, { showAsFullWidth }) => ({
extend: {
condition: showAsFullWidth,
style: {
flex: 1,
justifyContent: 'center',
},
},
}));

export const DeviceInfoButton = ({ showAsFullWidth }: DeviceInfoButtonProps) => {
const { applyStyle } = useNativeStyles();
const navigation = useNavigation<NavigationProp>();
const { setIsDeviceManagerVisible } = useDeviceManager();
const selectedDevice = useSelector(selectDevice);

const handleDeviceRedirect = () => {
setIsDeviceManagerVisible(false);
navigation.navigate(RootStackRoutes.DeviceInfo);
analytics.report({ type: EventType.DeviceManagerClick, payload: { action: 'deviceInfo' } });
};

if (!selectedDevice) return null;

return (
<DeviceAction
testID="@device-manager/device/info"
onPress={handleDeviceRedirect}
showAsFullWidth={showAsFullWidth}
>
<HStack spacing="small" style={applyStyle(contentStyle, { showAsFullWidth })}>
<Icon name="infoLight" size="mediumLarge" />
<Text variant="hint">
<Translation id="deviceManager.deviceButtons.deviceInfo" />
</Text>
</HStack>
</DeviceAction>
);
};
Loading

0 comments on commit 3cdd926

Please sign in to comment.