mirror of
https://github.com/trezor/trezor-suite.git
synced 2026-03-09 16:58:32 +01:00
feat(suite-native): device info detail (#9979)
This commit is contained in:
@@ -1,21 +1,34 @@
|
||||
import { FirmwareType, Device } from '@trezor/connect';
|
||||
import { FirmwareType, Device, VersionArray } from '@trezor/connect';
|
||||
|
||||
import { isDeviceInBootloaderMode } from './modeUtils';
|
||||
|
||||
export const getFirmwareRevision = (device?: Device) => device?.features?.revision || '';
|
||||
|
||||
export const getFirmwareVersionArray = (device?: Device): VersionArray | null => {
|
||||
if (!device?.features) {
|
||||
return null;
|
||||
}
|
||||
const { features } = device;
|
||||
|
||||
if (isDeviceInBootloaderMode(device)) {
|
||||
return features.fw_major && features.fw_minor && features.fw_patch
|
||||
? ([features.fw_major, features.fw_minor, features.fw_patch] as VersionArray)
|
||||
: null;
|
||||
}
|
||||
|
||||
return [features.major_version, features.minor_version, features.patch_version];
|
||||
};
|
||||
|
||||
export const getFirmwareVersion = (device?: Device) => {
|
||||
if (!device?.features) {
|
||||
return '';
|
||||
}
|
||||
const { features } = device;
|
||||
|
||||
if (isDeviceInBootloaderMode(device)) {
|
||||
return features.fw_major
|
||||
? `${features.fw_major}.${features.fw_minor}.${features.fw_patch}`
|
||||
: '';
|
||||
}
|
||||
|
||||
return `${features.major_version}.${features.minor_version}.${features.patch_version}`;
|
||||
};
|
||||
|
||||
|
||||
@@ -77,6 +77,13 @@ export const removeButtonRequests = createAction(
|
||||
}),
|
||||
);
|
||||
|
||||
export const forgetAndDisconnectDevice = createAction(
|
||||
`${MODULE_PREFIX}/forgetAndDisconnectDevice`,
|
||||
(payload: TrezorDevice) => ({
|
||||
payload,
|
||||
}),
|
||||
);
|
||||
|
||||
export const deviceActions = {
|
||||
connectDevice,
|
||||
connectUnacquiredDevice,
|
||||
@@ -94,4 +101,5 @@ export const deviceActions = {
|
||||
selectDevice,
|
||||
updateSelectedDevice,
|
||||
removeButtonRequests,
|
||||
forgetAndDisconnectDevice,
|
||||
};
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { memoize } from 'proxy-memoize';
|
||||
|
||||
import * as deviceUtils from '@suite-common/suite-utils';
|
||||
import { getStatus } from '@suite-common/suite-utils';
|
||||
import { Device, Features, AuthenticateDeviceResult } from '@trezor/connect';
|
||||
import { DiscoveryStatus } from '@suite-common/wallet-constants';
|
||||
import { getFirmwareVersion } from '@trezor/device-utils';
|
||||
import { getFirmwareVersion, getFirmwareVersionArray } from '@trezor/device-utils';
|
||||
import { Network, networks } from '@suite-common/wallet-config';
|
||||
import { versionUtils } from '@trezor/utils';
|
||||
import { createReducerWithExtraDeps } from '@suite-common/redux-utils';
|
||||
@@ -416,6 +418,11 @@ const forget = (draft: State, device: TrezorDevice) => {
|
||||
}
|
||||
};
|
||||
|
||||
const forgetAndDisconnect = (draft: State, device: TrezorDevice) => {
|
||||
forget(draft, device);
|
||||
disconnectDevice(draft, device);
|
||||
};
|
||||
|
||||
const addButtonRequest = (
|
||||
draft: State,
|
||||
device: TrezorDevice | undefined,
|
||||
@@ -498,7 +505,10 @@ export const prepareDeviceReducer = createReducerWithExtraDeps(initialState, (bu
|
||||
setDeviceAuthenticity(state, payload.device, payload.result);
|
||||
})
|
||||
.addCase(extra.actionTypes.setDeviceMetadata, extra.reducers.setDeviceMetadataReducer)
|
||||
.addCase(extra.actionTypes.storageLoad, extra.reducers.storageLoadDevices);
|
||||
.addCase(extra.actionTypes.storageLoad, extra.reducers.storageLoadDevices)
|
||||
.addCase(deviceActions.forgetAndDisconnectDevice, (state, { payload }) => {
|
||||
forgetAndDisconnect(state, payload);
|
||||
});
|
||||
});
|
||||
|
||||
export const selectDevices = (state: DeviceRootState) => state.device?.devices;
|
||||
@@ -687,13 +697,22 @@ export const selectSelectedDeviceName = (state: DeviceRootState) => {
|
||||
return selectDeviceName(state, selectedDevice?.id);
|
||||
};
|
||||
|
||||
export const selectDeviceFirmwareVersion = (state: DeviceRootState) => {
|
||||
const device = selectDevice(state);
|
||||
|
||||
return device?.firmwareRelease?.release.version ?? null;
|
||||
export const selectSelectedDeviceId = (state: DeviceRootState) => {
|
||||
const selectedDevice = selectDevice(state);
|
||||
return selectedDevice?.id ?? null;
|
||||
};
|
||||
|
||||
export const selectDeviceModel = (state: DeviceRootState) => {
|
||||
const features = selectDeviceFeatures(state);
|
||||
return features?.internal_model ?? null;
|
||||
};
|
||||
|
||||
export const selectDeviceReleaseInfo = (state: DeviceRootState) => {
|
||||
const device = selectDevice(state);
|
||||
return device?.firmwareRelease ?? null;
|
||||
};
|
||||
|
||||
export const selectDeviceFirmwareVersion = memoize((state: DeviceRootState) => {
|
||||
const device = selectDevice(state);
|
||||
return getFirmwareVersionArray(device);
|
||||
});
|
||||
|
||||
@@ -32,7 +32,7 @@ export const DeviceControlButtons = () => {
|
||||
if (!selectedDevice) return null;
|
||||
|
||||
const handleEject = () => {
|
||||
dispatch(deviceActions.forgetDevice(selectedDevice));
|
||||
dispatch(deviceActions.deviceDisconnect(selectedDevice));
|
||||
};
|
||||
|
||||
const handleDeviceRedirect = () => {
|
||||
|
||||
@@ -3,7 +3,11 @@ import { useSelector } from 'react-redux';
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
|
||||
import { Button, Text, VStack } from '@suite-native/atoms';
|
||||
import { selectDevices, selectIsSelectedDeviceImported } from '@suite-common/wallet-core';
|
||||
import {
|
||||
selectDevices,
|
||||
selectIsSelectedDeviceImported,
|
||||
selectSelectedDeviceId,
|
||||
} from '@suite-common/wallet-core';
|
||||
import {
|
||||
ConnectDeviceStackRoutes,
|
||||
RootStackParamList,
|
||||
@@ -29,6 +33,7 @@ export const DeviceManagerContent = () => {
|
||||
const { translate } = useTranslate();
|
||||
|
||||
const devices = useSelector(selectDevices);
|
||||
const selectedDeviceId = useSelector(selectSelectedDeviceId);
|
||||
const isPortfolioTrackerDevice = useSelector(selectIsSelectedDeviceImported);
|
||||
|
||||
const { setIsDeviceManagerVisible } = useDeviceManager();
|
||||
@@ -47,9 +52,12 @@ export const DeviceManagerContent = () => {
|
||||
<Text variant="callout">
|
||||
<Translation id="deviceManager.deviceList.sectionTitle" />
|
||||
</Text>
|
||||
{devices.map(device => (
|
||||
<DeviceItem key={device.path} id={device.id} />
|
||||
))}
|
||||
{devices.map(device => {
|
||||
if (device.id !== selectedDeviceId) {
|
||||
return <DeviceItem key={device.path} id={device.id} />;
|
||||
}
|
||||
return null;
|
||||
})}
|
||||
</VStack>
|
||||
{isPortfolioTrackerDevice && (
|
||||
<VStack>
|
||||
|
||||
@@ -21,11 +21,15 @@
|
||||
"@suite-native/feature-flags": "workspace:*",
|
||||
"@suite-native/helpers": "workspace:*",
|
||||
"@suite-native/intl": "workspace:*",
|
||||
"@suite-native/link": "workspace:*",
|
||||
"@suite-native/module-settings": "workspace:*",
|
||||
"@suite-native/navigation": "workspace:*",
|
||||
"@trezor/connect": "workspace:*",
|
||||
"@trezor/device-utils": "workspace:*",
|
||||
"@trezor/styles": "workspace:*",
|
||||
"react": "18.2.0",
|
||||
"react-redux": "8.0.7"
|
||||
"react-native": "0.71.8",
|
||||
"react-redux": "8.0.7",
|
||||
"semver": "^7.5.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
import { BottomSheet, VStack, Box, Button, Text } from '@suite-native/atoms';
|
||||
import { Translation, useTranslate } from '@suite-native/intl';
|
||||
import { useOpenLink } from '@suite-native/link';
|
||||
|
||||
export type HowToUpdateBottomSheetProps = {
|
||||
isVisible: boolean;
|
||||
onClose: (isVisible: boolean) => void;
|
||||
title?: string;
|
||||
};
|
||||
|
||||
export const HowToUpdateBottomSheet = ({
|
||||
isVisible,
|
||||
onClose,
|
||||
title,
|
||||
}: HowToUpdateBottomSheetProps) => {
|
||||
const { translate } = useTranslate();
|
||||
const openLink = useOpenLink();
|
||||
|
||||
const handleHelpClick = () => {
|
||||
openLink('https://trezor.io/learn/a/update-trezor-device-firmware');
|
||||
onClose(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<BottomSheet isVisible={isVisible} onClose={onClose} title={title}>
|
||||
<VStack spacing="large">
|
||||
<VStack paddingHorizontal="large">
|
||||
<Text variant="callout">
|
||||
<Translation id="deviceInfo.updateHowTo.subtitle" />
|
||||
</Text>
|
||||
<Box>
|
||||
<Text color="textSubdued">
|
||||
<Translation id="deviceInfo.updateHowTo.lines.1" />
|
||||
</Text>
|
||||
<Text color="textSubdued">
|
||||
<Translation id="deviceInfo.updateHowTo.lines.2" />
|
||||
</Text>
|
||||
<Text color="textSubdued">
|
||||
<Translation id="deviceInfo.updateHowTo.lines.3" />
|
||||
</Text>
|
||||
</Box>
|
||||
</VStack>
|
||||
<Button
|
||||
colorScheme="tertiaryElevation0"
|
||||
onPress={handleHelpClick}
|
||||
iconRight="arrowUpRight"
|
||||
>
|
||||
{translate('deviceInfo.updateHowTo.button')}
|
||||
</Button>
|
||||
</VStack>
|
||||
</BottomSheet>
|
||||
);
|
||||
};
|
||||
@@ -18,10 +18,10 @@ import {
|
||||
selectIsDeviceConnectedAndAuthorized,
|
||||
selectIsSelectedDeviceImported,
|
||||
selectIsUnacquiredDevice,
|
||||
selectDeviceFirmwareVersion,
|
||||
selectDeviceModel,
|
||||
selectDevice,
|
||||
deviceActions,
|
||||
selectDeviceFirmwareVersion,
|
||||
} from '@suite-common/wallet-core';
|
||||
import { useAlert } from '@suite-native/alerts';
|
||||
import { Translation, useTranslate } from '@suite-native/intl';
|
||||
@@ -56,15 +56,15 @@ type NavigationProps = StackToStackCompositeNavigationProps<
|
||||
>;
|
||||
|
||||
export const useDeviceConnect = () => {
|
||||
const deviceModel = useSelector(selectDeviceModel);
|
||||
const currentDevice = useSelector(selectDevice);
|
||||
const hasDeviceRequestedPin = useSelector(selectDeviceRequestedPin);
|
||||
const isDeviceConnectedAndAuthorized = useSelector(selectIsDeviceConnectedAndAuthorized);
|
||||
const isUnacquiredDevice = useSelector(selectIsUnacquiredDevice);
|
||||
const isConnectedDeviceUninitialized = useSelector(selectIsConnectedDeviceUninitialized);
|
||||
const isSelectedDeviceImported = useSelector(selectIsSelectedDeviceImported);
|
||||
const firmwareVersion = useSelector(selectDeviceFirmwareVersion);
|
||||
const deviceModel = useSelector(selectDeviceModel);
|
||||
const currentDevice = useSelector(selectDevice);
|
||||
const isOnboardingFinished = useSelector(selectIsOnboardingFinished);
|
||||
const deviceFwVersion = useSelector(selectDeviceFirmwareVersion);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
@@ -80,6 +80,8 @@ export const useDeviceConnect = () => {
|
||||
}
|
||||
}, [currentDevice, dispatch]);
|
||||
|
||||
const isFirmwareSupported = isFirmwareVersionSupported(deviceFwVersion, deviceModel);
|
||||
|
||||
useEffect(() => {
|
||||
if (hasDeviceRequestedPin) {
|
||||
navigation.navigate(RootStackRoutes.ConnectDevice, {
|
||||
@@ -106,7 +108,7 @@ export const useDeviceConnect = () => {
|
||||
}, [dispatch, hideAlert, isOnboardingFinished, isUnacquiredDevice, showAlert, translate]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isOnboardingFinished && !isFirmwareVersionSupported(firmwareVersion, deviceModel)) {
|
||||
if (isOnboardingFinished && !isFirmwareSupported && !isSelectedDeviceImported) {
|
||||
showAlert({
|
||||
title: translate('moduleDevice.unsupportedFirmware.title'),
|
||||
description: translate('moduleDevice.unsupportedFirmware.description'),
|
||||
@@ -120,12 +122,12 @@ export const useDeviceConnect = () => {
|
||||
}
|
||||
}, [
|
||||
dispatch,
|
||||
firmwareVersion,
|
||||
deviceModel,
|
||||
isFirmwareSupported,
|
||||
showAlert,
|
||||
translate,
|
||||
handleDisconnect,
|
||||
isOnboardingFinished,
|
||||
isSelectedDeviceImported,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -53,7 +53,10 @@ export const prepareDeviceMiddleware = createMiddlewareWithExtraDeps(
|
||||
dispatch(authorizeDevice({ isUseEmptyPassphraseForced: true }));
|
||||
}
|
||||
|
||||
if (deviceActions.forgetDevice.match(action)) {
|
||||
if (
|
||||
deviceActions.forgetDevice.match(action) ||
|
||||
deviceActions.forgetAndDisconnectDevice.match(action)
|
||||
) {
|
||||
dispatch(handleDeviceDisconnect(action.payload));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useSelector } from 'react-redux';
|
||||
import { useEffect } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { G } from '@mobily/ts-belt';
|
||||
import { CommonActions, useNavigation } from '@react-navigation/native';
|
||||
|
||||
import { DeviceModelInternal } from '@trezor/connect';
|
||||
@@ -9,19 +10,26 @@ import {
|
||||
Box,
|
||||
Card,
|
||||
HStack,
|
||||
VStack,
|
||||
Button,
|
||||
IconButton,
|
||||
ScreenHeaderWrapper,
|
||||
Text,
|
||||
} from '@suite-native/atoms';
|
||||
import { HomeStackRoutes, RootStackRoutes, Screen } from '@suite-native/navigation';
|
||||
import {
|
||||
selectDeviceFirmwareVersion,
|
||||
selectDevice,
|
||||
selectDeviceModel,
|
||||
selectDeviceReleaseInfo,
|
||||
selectIsSelectedDeviceImported,
|
||||
selectSelectedDeviceName,
|
||||
} from '@suite-common/wallet-core';
|
||||
import { prepareNativeStyle, useNativeStyles } from '@trezor/styles';
|
||||
import { useTranslate } from '@suite-native/intl';
|
||||
import { getFirmwareVersion } from '@trezor/device-utils';
|
||||
import { useOpenLink } from '@suite-native/link';
|
||||
|
||||
import { HowToUpdateBottomSheet } from '../components/HowToUpdateBottomSheet';
|
||||
|
||||
const deviceImage = {
|
||||
[DeviceModelInternal.T1B1]: require('../assets/t1.png'),
|
||||
@@ -33,18 +41,44 @@ const emptyBoxStyle = prepareNativeStyle(() => ({
|
||||
width: 48,
|
||||
}));
|
||||
|
||||
const contentStyle = prepareNativeStyle(() => ({
|
||||
flexGrow: 1,
|
||||
}));
|
||||
|
||||
export const DeviceInfoModalScreen = () => {
|
||||
const navigation = useNavigation();
|
||||
|
||||
const { translate } = useTranslate();
|
||||
const openLink = useOpenLink();
|
||||
|
||||
const deviceModel = useSelector(selectDeviceModel);
|
||||
const deviceName = useSelector(selectSelectedDeviceName);
|
||||
const deviceFirmwareVersion = useSelector(selectDeviceFirmwareVersion);
|
||||
const device = useSelector(selectDevice);
|
||||
const isPortfolioTrackerDevice = useSelector(selectIsSelectedDeviceImported);
|
||||
|
||||
const deviceReleaseInfo = useSelector(selectDeviceReleaseInfo);
|
||||
const { applyStyle } = useNativeStyles();
|
||||
|
||||
const [isUpdateSheetOpen, setIsUpdateSheetOpen] = useState<boolean>(false);
|
||||
|
||||
const isUpgradable = deviceReleaseInfo?.isNewer ?? false;
|
||||
|
||||
const getCardAlertProps = () => {
|
||||
if (G.isNotNullable(deviceReleaseInfo)) {
|
||||
if (isUpgradable) {
|
||||
return {
|
||||
alertTitle: translate('deviceInfo.outdatedFw'),
|
||||
alertVariant: 'warning',
|
||||
} as const;
|
||||
}
|
||||
return {
|
||||
alertTitle: translate('deviceInfo.upToDateFw'),
|
||||
alertVariant: 'success',
|
||||
} as const;
|
||||
}
|
||||
|
||||
return { alertTitle: undefined, alertVariant: undefined } as const;
|
||||
};
|
||||
const cardAlertProps = getCardAlertProps();
|
||||
|
||||
useEffect(() => {
|
||||
if (isPortfolioTrackerDevice) {
|
||||
// Should be part of useDeviceConnect hook
|
||||
@@ -67,12 +101,17 @@ export const DeviceInfoModalScreen = () => {
|
||||
|
||||
if (!deviceModel) return null;
|
||||
|
||||
const currentFwVersion = getFirmwareVersion(device);
|
||||
|
||||
const handleGoBack = () => {
|
||||
navigation.goBack();
|
||||
};
|
||||
|
||||
const stringifiedFirmwareVersion = deviceFirmwareVersion?.join('.');
|
||||
const handleAccessoriesClick = () => {
|
||||
openLink('https://trezor.io/accessories');
|
||||
};
|
||||
|
||||
const handleUpdateClick = () => setIsUpdateSheetOpen(true);
|
||||
return (
|
||||
<Screen
|
||||
screenHeader={
|
||||
@@ -88,17 +127,40 @@ export const DeviceInfoModalScreen = () => {
|
||||
</ScreenHeaderWrapper>
|
||||
}
|
||||
>
|
||||
<Card>
|
||||
<HStack spacing="large">
|
||||
<Image width={92} height={151} source={deviceImage[deviceModel]} />
|
||||
<Box justifyContent="center">
|
||||
<Text variant="titleSmall">{deviceName}</Text>
|
||||
<Text variant="hint">
|
||||
{translate('deviceInfo.installedFw', { stringifiedFirmwareVersion })}
|
||||
</Text>
|
||||
</Box>
|
||||
</HStack>
|
||||
</Card>
|
||||
<Box style={applyStyle(contentStyle)}>
|
||||
<Card {...cardAlertProps}>
|
||||
<HStack spacing="large">
|
||||
<Image width={92} height={151} source={deviceImage[deviceModel]} />
|
||||
<Box justifyContent="center">
|
||||
<Text variant="titleSmall">{deviceName}</Text>
|
||||
<Text variant="hint">
|
||||
{translate('deviceInfo.installedFw', {
|
||||
version: currentFwVersion,
|
||||
})}
|
||||
</Text>
|
||||
</Box>
|
||||
</HStack>
|
||||
</Card>
|
||||
</Box>
|
||||
<VStack spacing="medium">
|
||||
<Button
|
||||
colorScheme="tertiaryElevation0"
|
||||
onPress={handleAccessoriesClick}
|
||||
iconRight="arrowUpRight"
|
||||
>
|
||||
{translate('deviceInfo.goToAccessories')}
|
||||
</Button>
|
||||
{isUpgradable && (
|
||||
<Button colorScheme="primary" onPress={handleUpdateClick}>
|
||||
{translate('deviceInfo.updateHowTo.title')}
|
||||
</Button>
|
||||
)}
|
||||
</VStack>
|
||||
<HowToUpdateBottomSheet
|
||||
isVisible={isUpdateSheetOpen}
|
||||
onClose={setIsUpdateSheetOpen}
|
||||
title={translate('deviceInfo.updateHowTo.title')}
|
||||
/>
|
||||
</Screen>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { A, G } from '@mobily/ts-belt';
|
||||
import { G } from '@mobily/ts-belt';
|
||||
import * as semver from 'semver';
|
||||
|
||||
import { DeviceModelInternal, VersionArray } from '@trezor/connect';
|
||||
|
||||
@@ -18,8 +19,8 @@ export const isFirmwareVersionSupported = (
|
||||
|
||||
if (!minimalVersion) return true;
|
||||
|
||||
return A.every(
|
||||
version.map((v, i) => v >= minimalVersion[i]),
|
||||
val => val,
|
||||
);
|
||||
const versionString = version.join('.');
|
||||
const minimalVersionString = minimalVersion.join('.');
|
||||
|
||||
return semver.satisfies(versionString, `>=${minimalVersionString}`);
|
||||
};
|
||||
|
||||
@@ -13,9 +13,11 @@
|
||||
{ "path": "../feature-flags" },
|
||||
{ "path": "../helpers" },
|
||||
{ "path": "../intl" },
|
||||
{ "path": "../link" },
|
||||
{ "path": "../module-settings" },
|
||||
{ "path": "../navigation" },
|
||||
{ "path": "../../packages/connect" },
|
||||
{ "path": "../../packages/device-utils" },
|
||||
{ "path": "../../packages/styles" }
|
||||
]
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
"@suite-native/accounts": "workspace:*",
|
||||
"@suite-native/config": "workspace:*",
|
||||
"@suite-native/device": "workspace:*",
|
||||
"@trezor/connect": "workspace:*"
|
||||
"@trezor/connect": "workspace:*",
|
||||
"@trezor/device-utils": "workspace:*"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ import {
|
||||
deviceActions,
|
||||
selectDevice,
|
||||
discoveryActions,
|
||||
selectDeviceFirmwareVersion,
|
||||
selectDeviceModel,
|
||||
selectDeviceFirmwareVersion,
|
||||
} from '@suite-common/wallet-core';
|
||||
import { createMiddlewareWithExtraDeps } from '@suite-common/redux-utils';
|
||||
import { isFirmwareVersionSupported } from '@suite-native/device';
|
||||
@@ -19,12 +19,12 @@ export const prepareDiscoveryMiddleware = createMiddlewareWithExtraDeps(
|
||||
|
||||
const device = selectDevice(getState());
|
||||
const deviceModel = selectDeviceModel(getState());
|
||||
const deviceFirmwareVersion = selectDeviceFirmwareVersion(getState());
|
||||
const deviceFwVersion = selectDeviceFirmwareVersion(getState());
|
||||
|
||||
const areTestnetsEnabled = selectAreTestnetsEnabled(getState());
|
||||
|
||||
const isDeviceFirmwareVersionSupported = isFirmwareVersionSupported(
|
||||
deviceFirmwareVersion,
|
||||
deviceFwVersion,
|
||||
deviceModel,
|
||||
);
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
{ "path": "../accounts" },
|
||||
{ "path": "../config" },
|
||||
{ "path": "../device" },
|
||||
{ "path": "../../packages/connect" }
|
||||
{ "path": "../../packages/connect" },
|
||||
{ "path": "../../packages/device-utils" }
|
||||
]
|
||||
}
|
||||
|
||||
@@ -305,6 +305,19 @@ export const en = {
|
||||
},
|
||||
deviceInfo: {
|
||||
installedFw: 'Installed firmware: {version}',
|
||||
upToDateFw: 'The firmware is up to date.',
|
||||
outdatedFw: 'The firmware is outdated.',
|
||||
goToAccessories: 'Get accessories @ Trezor Shop',
|
||||
updateHowTo: {
|
||||
title: 'How to update firmware',
|
||||
subtitle: 'Follow these steps:',
|
||||
lines: {
|
||||
1: '1. Connect Trezor to Desktop Suite',
|
||||
2: '2. Navigate to Settings menu',
|
||||
3: '3. Install new firmware',
|
||||
},
|
||||
button: 'Learn more @ Trezor.io',
|
||||
},
|
||||
},
|
||||
qrCode: {
|
||||
addressCopied: 'Address copied',
|
||||
|
||||
@@ -7385,12 +7385,16 @@ __metadata:
|
||||
"@suite-native/feature-flags": "workspace:*"
|
||||
"@suite-native/helpers": "workspace:*"
|
||||
"@suite-native/intl": "workspace:*"
|
||||
"@suite-native/link": "workspace:*"
|
||||
"@suite-native/module-settings": "workspace:*"
|
||||
"@suite-native/navigation": "workspace:*"
|
||||
"@trezor/connect": "workspace:*"
|
||||
"@trezor/device-utils": "workspace:*"
|
||||
"@trezor/styles": "workspace:*"
|
||||
react: "npm:18.2.0"
|
||||
react-native: "npm:0.71.8"
|
||||
react-redux: "npm:8.0.7"
|
||||
semver: "npm:^7.5.4"
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
@@ -7411,6 +7415,7 @@ __metadata:
|
||||
"@suite-native/config": "workspace:*"
|
||||
"@suite-native/device": "workspace:*"
|
||||
"@trezor/connect": "workspace:*"
|
||||
"@trezor/device-utils": "workspace:*"
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
|
||||
Reference in New Issue
Block a user