From 794445f08a6cf2ba0f4b977669aabdc4691a18e7 Mon Sep 17 00:00:00 2001 From: yanas Date: Tue, 8 Oct 2024 11:39:33 +0200 Subject: [PATCH] feat(suite-native): rework layout of the Device info screen --- packages/theme/src/borders.ts | 1 + suite-native/atoms/src/AlertBox.tsx | 13 +- suite-native/atoms/src/index.ts | 1 + suite-native/atoms/src/utils.ts | 7 ++ suite-native/device/package.json | 2 + .../src/components/DeviceFirmwareCard.tsx | 110 +++++++++++++++++ .../src/screens/DeviceInfoModalScreen.tsx | 113 +++--------------- suite-native/device/tsconfig.json | 6 + suite-native/intl/src/en.ts | 12 ++ .../navigation/src/components/Screen.tsx | 18 +-- .../src/components/ScreenSubHeader.tsx | 17 ++- yarn.lock | 2 + 12 files changed, 185 insertions(+), 117 deletions(-) create mode 100644 suite-native/atoms/src/utils.ts create mode 100644 suite-native/device/src/components/DeviceFirmwareCard.tsx diff --git a/packages/theme/src/borders.ts b/packages/theme/src/borders.ts index ec86d988e23..fde3c68c1b3 100644 --- a/packages/theme/src/borders.ts +++ b/packages/theme/src/borders.ts @@ -36,3 +36,4 @@ export const nativeBorders = { } as const; export type NativeBorders = typeof nativeBorders; +export type NativeRadius = keyof typeof nativeBorders.radii; diff --git a/suite-native/atoms/src/AlertBox.tsx b/suite-native/atoms/src/AlertBox.tsx index 18d77c13409..676c31cf199 100644 --- a/suite-native/atoms/src/AlertBox.tsx +++ b/suite-native/atoms/src/AlertBox.tsx @@ -2,11 +2,12 @@ import { ReactNode } from 'react'; import { ActivityIndicator } from 'react-native'; import { prepareNativeStyle, useNativeStyles } from '@trezor/styles'; -import { Color, nativeBorders } from '@trezor/theme'; +import { Color, NativeRadius } from '@trezor/theme'; import { Icon, IconName } from '@suite-common/icons-deprecated'; import { Box } from './Box'; import { Text } from './Text'; +import { nativeRadiusToNumber } from './utils'; export type AlertBoxVariant = 'info' | 'success' | 'warning' | 'loading' | 'error'; @@ -80,7 +81,7 @@ const variantToIconName = { export type AlertBoxProps = { variant: AlertBoxVariant; title: ReactNode; - borderRadius?: number; + borderRadius?: NativeRadius | number; }; const AlertSpinner = ({ color }: { color: Color }) => { @@ -91,18 +92,14 @@ const AlertSpinner = ({ color }: { color: Color }) => { return ; }; -export const AlertBox = ({ - title, - variant = 'info', - borderRadius = nativeBorders.radii.r16, -}: AlertBoxProps) => { +export const AlertBox = ({ title, variant = 'info', borderRadius = 'r16' }: AlertBoxProps) => { const { applyStyle } = useNativeStyles(); const { contentColor, backgroundColor, borderColor } = variantToColorMap[variant]; return ( + typeof value === 'number' ? value : nativeSpacings[value]; + +export const nativeRadiusToNumber = (value: NativeRadius | number) => + typeof value === 'number' ? value : nativeBorders.radii[value]; diff --git a/suite-native/device/package.json b/suite-native/device/package.json index 1073b149938..e4cee8a2bbc 100644 --- a/suite-native/device/package.json +++ b/suite-native/device/package.json @@ -15,7 +15,9 @@ "@react-navigation/native": "6.1.18", "@reduxjs/toolkit": "1.9.5", "@sentry/react-native": "5.33.0", + "@suite-common/icons-deprecated": "workspace:*", "@suite-common/redux-utils": "workspace:*", + "@suite-common/suite-utils": "workspace:*", "@suite-common/wallet-core": "workspace:*", "@suite-common/wallet-utils": "workspace:*", "@suite-native/alerts": "workspace:*", diff --git a/suite-native/device/src/components/DeviceFirmwareCard.tsx b/suite-native/device/src/components/DeviceFirmwareCard.tsx new file mode 100644 index 00000000000..4929eb7eae3 --- /dev/null +++ b/suite-native/device/src/components/DeviceFirmwareCard.tsx @@ -0,0 +1,110 @@ +import { ReactNode } from 'react'; +import { useSelector } from 'react-redux'; + +import { G } from '@mobily/ts-belt'; + +import { getFwUpdateVersion } from '@suite-common/suite-utils'; +import { DeviceModelIcon } from '@suite-common/icons-deprecated'; +import { + selectDevice, + selectDeviceModel, + selectDeviceReleaseInfo, +} from '@suite-common/wallet-core'; +import { AlertBox, Box, Card, HStack, Text, VStack } from '@suite-native/atoms'; +import { Translation } from '@suite-native/intl'; +import { getFirmwareVersion, hasBitcoinOnlyFirmware } from '@trezor/device-utils'; +import { prepareNativeStyle, useNativeStyles } from '@trezor/styles'; + +const vStackStyle = prepareNativeStyle(() => ({ + flexGrow: 1, +})); + +type DeviceInfoProps = { + label: ReactNode; + value: ReactNode; +}; + +const FirmwareInfo = ({ label, value }: DeviceInfoProps) => { + const { applyStyle } = useNativeStyles(); + + return ( + + + {label} + + {value} + + ); +}; + +export const DeviceFirmwareCard = () => { + const { applyStyle } = useNativeStyles(); + + const device = useSelector(selectDevice); + const deviceModel = useSelector(selectDeviceModel); + const deviceReleaseInfo = useSelector(selectDeviceReleaseInfo); + + if (!device || !deviceModel) { + return null; + } + + const firmwareVersion = getFirmwareVersion(device); + const firmwareTypeTranslationId = hasBitcoinOnlyFirmware(device) + ? 'deviceSettings.firmware.typeBitcoinOnly' + : 'deviceSettings.firmware.typeUniversal'; + + const firmwareUpdateProps = (() => { + if (G.isNotNullable(deviceReleaseInfo)) { + const isUpgradable = deviceReleaseInfo.isNewer ?? false; + + if (isUpgradable) { + return { + title: ( + + ), + variant: 'info', + } as const; + } + + return { + title: , + variant: 'success', + } as const; + } + + return undefined; + })(); + + return ( + + + + + + + + + + + } + value={firmwareVersion} + /> + } + value={} + /> + + + + {firmwareUpdateProps && ( + + + + )} + + ); +}; diff --git a/suite-native/device/src/screens/DeviceInfoModalScreen.tsx b/suite-native/device/src/screens/DeviceInfoModalScreen.tsx index 7e0fe21f01a..7486f528aa9 100644 --- a/suite-native/device/src/screens/DeviceInfoModalScreen.tsx +++ b/suite-native/device/src/screens/DeviceInfoModalScreen.tsx @@ -1,41 +1,28 @@ import { useSelector } from 'react-redux'; import { useEffect, useState } from 'react'; -import { G } from '@mobily/ts-belt'; import { useNavigation } from '@react-navigation/native'; import { DeviceModelInternal } from '@trezor/connect'; -import { - Image, - Box, - Card, - HStack, - VStack, - Button, - IconButton, - ScreenHeaderWrapper, - Text, -} from '@suite-native/atoms'; +import { Image, VStack, Button, Text } from '@suite-native/atoms'; import { AppTabsRoutes, HomeStackRoutes, RootStackParamList, RootStackRoutes, Screen, + ScreenSubHeader, StackNavigationProps, } from '@suite-native/navigation'; import { selectDevice, - selectDeviceLabel, selectDeviceModel, selectDeviceReleaseInfo, selectIsPortfolioTrackerDevice, } from '@suite-common/wallet-core'; -import { prepareNativeStyle, useNativeStyles } from '@trezor/styles'; import { Translation, useTranslate } from '@suite-native/intl'; -import { getFirmwareVersion } from '@trezor/device-utils'; -import { useOpenLink } from '@suite-native/link'; +import { DeviceFirmwareCard } from '../components/DeviceFirmwareCard'; import { HowToUpdateBottomSheet } from '../components/HowToUpdateBottomSheet'; const deviceImageMap: Record = { @@ -46,51 +33,21 @@ const deviceImageMap: Record = { [DeviceModelInternal.T3T1]: require('../assets/t3t1.png'), }; -const emptyBoxStyle = prepareNativeStyle(() => ({ - width: 48, -})); - -const contentStyle = prepareNativeStyle(() => ({ - flexGrow: 1, -})); - type NavigationProp = StackNavigationProps; export const DeviceInfoModalScreen = () => { const navigation = useNavigation(); const { translate } = useTranslate(); - const openLink = useOpenLink(); - const deviceModel = useSelector(selectDeviceModel); - const deviceLabel = useSelector(selectDeviceLabel); const device = useSelector(selectDevice); + const deviceModel = useSelector(selectDeviceModel); const isPortfolioTrackerDevice = useSelector(selectIsPortfolioTrackerDevice); const deviceReleaseInfo = useSelector(selectDeviceReleaseInfo); - const { applyStyle } = useNativeStyles(); const [isUpdateSheetOpen, setIsUpdateSheetOpen] = useState(false); const isUpgradable = deviceReleaseInfo?.isNewer ?? false; - const getCardAlertProps = () => { - if (G.isNotNullable(deviceReleaseInfo)) { - if (isUpgradable) { - return { - alertTitle: , - alertVariant: 'warning', - } as const; - } - - return { - alertTitle: , - alertVariant: 'success', - } as const; - } - - return { alertTitle: undefined, alertVariant: undefined } as const; - }; - const cardAlertProps = getCardAlertProps(); - useEffect(() => { if (isPortfolioTrackerDevice) { navigation.navigate(RootStackRoutes.AppTabs, { @@ -102,61 +59,29 @@ export const DeviceInfoModalScreen = () => { } }, [isPortfolioTrackerDevice, navigation]); - if (!deviceModel) return null; - - const currentFwVersion = getFirmwareVersion(device); - - const handleGoBack = () => { - navigation.goBack(); - }; - - const handleAccessoriesClick = () => { - openLink('https://trezor.io/accessories'); - }; + if (!device || !deviceModel) { + return null; + } const handleUpdateClick = () => setIsUpdateSheetOpen(true); return ( - - Device info - - + } + customHorizontalPadding="sp16" > - - - - - - {deviceLabel && {deviceLabel}} - - {device?.name} - - - {translate('deviceInfo.installedFw', { - version: currentFwVersion, - })} - - - - - - - + + + {device.name} + + + {isUpgradable && (