diff --git a/apps/desktop/package.json b/apps/desktop/package.json index ed308a10556..e54a378eb1e 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -36,7 +36,7 @@ "@onekeyhq/kit": "*", "@sentry/electron": "5.8.0", "adm-zip": "^0.5.10", - "electron-check-biometric-auth-changed": "0.0.4", + "electron-check-biometric-auth-changed": "0.0.6", "electron-context-menu": "^3.5.0", "electron-is-dev": "^2.0.0", "electron-log": "5.2.0", diff --git a/apps/desktop/scripts/build.js b/apps/desktop/scripts/build.js index 27802a350e6..f3ad98b819a 100644 --- a/apps/desktop/scripts/build.js +++ b/apps/desktop/scripts/build.js @@ -1,6 +1,7 @@ const path = require('path'); const childProcess = require('child_process'); const { build } = require('esbuild'); +const glob = require('glob'); const pkg = require('../package.json'); const electronSource = path.join(__dirname, '..', 'src-electron'); @@ -13,8 +14,14 @@ const gitRevision = childProcess const isProduction = process.env.NODE_ENV === 'production'; const hrstart = process.hrtime(); + +// Get all .js files in service directory +const serviceFiles = glob + .sync(path.join(electronSource, 'service', '*.ts')) + .map((name) => name.split('src-electron/').pop()); + build({ - entryPoints: ['app.ts', 'preload.ts', 'service/windowsHello.ts'].map((f) => + entryPoints: ['app.ts', 'preload.ts', ...serviceFiles].map((f) => path.join(electronSource, f), ), platform: 'node', diff --git a/apps/desktop/src-electron/app.ts b/apps/desktop/src-electron/app.ts index 14820b31457..720e21bb638 100644 --- a/apps/desktop/src-electron/app.ts +++ b/apps/desktop/src-electron/app.ts @@ -18,7 +18,6 @@ import { shell, systemPreferences, } from 'electron'; -import { checkBiometricAuthChanged } from 'electron-check-biometric-auth-changed'; import contextMenu from 'electron-context-menu'; import isDev from 'electron-is-dev'; import logger from 'electron-log/main'; @@ -47,6 +46,7 @@ import { resourcesPath, staticPath } from './resoucePath'; import { initSentry } from './sentry'; import { checkAvailabilityAsync, + checkBiometricAuthChanged, requestVerificationAsync, startServices, } from './service'; @@ -581,12 +581,18 @@ function createMainWindow() { event.returnValue = isDev; }); - ipcMain.on(ipcMessageKeys.CHECK_BIOMETRIC_AUTH_CHANGED, (event) => { + ipcMain.on(ipcMessageKeys.CHECK_BIOMETRIC_AUTH_CHANGED, async (event) => { if (!isMac) { event.returnValue = false; return; } - event.returnValue = checkBiometricAuthChanged(); + try { + const result = await checkBiometricAuthChanged(); + event.returnValue = result; + } catch (error) { + logger.error('[CHECK_BIOMETRIC_AUTH_CHANGED] Error:', error); + event.returnValue = false; + } }); ipcMain.on(ipcMessageKeys.TOUCH_ID_CAN_PROMPT, async (event) => { diff --git a/apps/desktop/src-electron/service/checkBiometricAuthChanged.ts b/apps/desktop/src-electron/service/checkBiometricAuthChanged.ts new file mode 100644 index 00000000000..56b6c89c575 --- /dev/null +++ b/apps/desktop/src-electron/service/checkBiometricAuthChanged.ts @@ -0,0 +1,25 @@ +import { checkBiometricAuthChanged } from 'electron-check-biometric-auth-changed'; + +import { ECheckBiometricAuthChangedEventType } from './enum'; + +// Child process +process.parentPort.on( + 'message', + (e: { + data: { type: ECheckBiometricAuthChangedEventType; params: unknown }; + }) => { + switch (e.data.type) { + case ECheckBiometricAuthChangedEventType.CheckBiometricAuthChanged: + { + const result = checkBiometricAuthChanged(); + process.parentPort.postMessage({ + type: ECheckBiometricAuthChangedEventType.CheckBiometricAuthChanged, + result, + }); + } + break; + default: + break; + } + }, +); diff --git a/apps/desktop/src-electron/service/enum.ts b/apps/desktop/src-electron/service/enum.ts index f9cde16a3c7..ba6f3fa1b99 100644 --- a/apps/desktop/src-electron/service/enum.ts +++ b/apps/desktop/src-electron/service/enum.ts @@ -2,3 +2,7 @@ export enum EWindowHelloEventType { CheckAvailabilityAsync = 'checkAvailabilityAsync', RequestVerificationAsync = 'requestVerificationAsync', } + +export enum ECheckBiometricAuthChangedEventType { + CheckBiometricAuthChanged = 'checkBiometricAuthChanged', +} diff --git a/apps/desktop/src-electron/service/index.ts b/apps/desktop/src-electron/service/index.ts index a0d80c64dab..ae2f48f5bb8 100644 --- a/apps/desktop/src-electron/service/index.ts +++ b/apps/desktop/src-electron/service/index.ts @@ -3,26 +3,51 @@ import path from 'path'; import { utilityProcess } from 'electron/main'; import Logger from 'electron-log/main'; -import { EWindowHelloEventType } from './enum'; +import { + ECheckBiometricAuthChangedEventType, + EWindowHelloEventType, +} from './enum'; import type { UtilityProcess } from 'electron/main'; -let windowsHelloChildProcess: UtilityProcess | null = null; -let windowsHelloCallbacks: { - type: string; - callback: (e: any) => void; - timestamp: number; -}[] = []; -export const startServices = () => { - windowsHelloChildProcess = utilityProcess.fork( - // After build, the directory is 'dist' and WindowsHello file is located in 'dist/service' - path.join(__dirname, './service/windowsHello.js'), - ); - windowsHelloChildProcess.on( +enum EServiceName { + WindowsHello = 'windowsHello', + CheckBiometricAuthChanged = 'checkBiometricAuthChanged', +} + +const processConfig: Record< + EServiceName, + { + childProcess: UtilityProcess | null; + callbacks: { + type: string; + callback: (e: any) => void; + timestamp: number; + }[]; + } +> = { + [EServiceName.WindowsHello]: { + childProcess: null, + callbacks: [], + }, + [EServiceName.CheckBiometricAuthChanged]: { + childProcess: null, + callbacks: [], + }, +}; + +const startService = (key: EServiceName) => { + if (!processConfig[key].childProcess) { + processConfig[key].childProcess = utilityProcess.fork( + path.join(__dirname, `./service/${key}.js`), + ); + } + + processConfig[key].childProcess?.on( 'message', (e: { type: string; result: boolean }) => { - Logger.info('windowsHelloChildProcess-onMessage', e); - const callbacks = windowsHelloCallbacks.filter( + Logger.info(`${key}ChildProcess-onMessage`, e); + const callbacks = processConfig[key].callbacks.filter( (callbackItem) => callbackItem.type === e.type, ); if (callbacks.length) { @@ -32,31 +57,47 @@ export const startServices = () => { callbackItem.callback(e.result); } }); - windowsHelloCallbacks = windowsHelloCallbacks.filter( + processConfig[key].callbacks = processConfig[key].callbacks.filter( (callbackItem) => !callbacks.includes(callbackItem), ); } }, ); - windowsHelloChildProcess.on('exit', (code) => { - Logger.info('windowsHelloChildProcess--onExit', code); + processConfig[key].childProcess?.on('exit', (code) => { + Logger.info(`${key}ChildProcess--onExit`, code); + }); +}; +export const startServices = () => { + (Object.keys(processConfig) as EServiceName[]).forEach((key) => { + startService(key); }); }; +const postServiceMessage = ( + serviceName: EServiceName, + type: string, + params?: any, +): Promise => + new Promise((resolve) => { + processConfig[serviceName].callbacks.push({ + type, + callback: resolve, + timestamp: Date.now(), + }); + processConfig[serviceName].childProcess?.postMessage({ + type, + params, + }); + }); + let cacheWindowsHelloSupported: boolean | null = null; export const checkAvailabilityAsync = async () => { if (cacheWindowsHelloSupported === null) { cacheWindowsHelloSupported = await Promise.race([ - new Promise((resolve) => { - windowsHelloCallbacks.push({ - type: EWindowHelloEventType.CheckAvailabilityAsync, - callback: resolve, - timestamp: Date.now(), - }); - windowsHelloChildProcess?.postMessage({ - type: EWindowHelloEventType.CheckAvailabilityAsync, - }); - }), + postServiceMessage( + EServiceName.WindowsHello, + EWindowHelloEventType.CheckAvailabilityAsync, + ), new Promise((resolve) => setTimeout(() => { cacheWindowsHelloSupported = false; @@ -69,17 +110,24 @@ export const checkAvailabilityAsync = async () => { }; export const requestVerificationAsync = (message: string) => - new Promise<{ + postServiceMessage<{ success: boolean; error?: string; - }>((resolve) => { - windowsHelloCallbacks.push({ - type: EWindowHelloEventType.RequestVerificationAsync, - callback: resolve, - timestamp: Date.now(), - }); - windowsHelloChildProcess?.postMessage({ - type: EWindowHelloEventType.RequestVerificationAsync, - params: message, - }); - }); + }>( + EServiceName.WindowsHello, + EWindowHelloEventType.RequestVerificationAsync, + message, + ); + +export const checkBiometricAuthChanged = async () => + Promise.race([ + postServiceMessage( + EServiceName.CheckBiometricAuthChanged, + ECheckBiometricAuthChangedEventType.CheckBiometricAuthChanged, + ), + new Promise((resolve) => + setTimeout(() => { + resolve(false); + }, 500), + ), + ]); diff --git a/apps/desktop/src-electron/service/windowsHello.ts b/apps/desktop/src-electron/service/windowsHello.ts index 4fc6513f1ef..dc2f1baac8e 100644 --- a/apps/desktop/src-electron/service/windowsHello.ts +++ b/apps/desktop/src-electron/service/windowsHello.ts @@ -45,9 +45,9 @@ function requestVerificationAsync( // Child process process.parentPort.on( 'message', - (e: { data: { type: string; params: unknown } }) => { + (e: { data: { type: EWindowHelloEventType; params: unknown } }) => { switch (e.data.type) { - case 'checkAvailabilityAsync': + case EWindowHelloEventType.CheckAvailabilityAsync: checkWindowsHelloAvailability((result) => { process.parentPort.postMessage({ type: EWindowHelloEventType.CheckAvailabilityAsync, @@ -55,7 +55,7 @@ process.parentPort.on( }); }); break; - case 'requestVerificationAsync': + case EWindowHelloEventType.RequestVerificationAsync: requestVerificationAsync(e.data.params as string, (result) => { process.parentPort.postMessage({ type: EWindowHelloEventType.RequestVerificationAsync, diff --git a/package.json b/package.json index e1ea461a458..d812ebe781e 100644 --- a/package.json +++ b/package.json @@ -65,11 +65,11 @@ "@onekeyfe/cross-inpage-provider-injected": "2.2.10", "@onekeyfe/cross-inpage-provider-types": "2.2.10", "@onekeyfe/extension-bridge-hosted": "2.2.10", - "@onekeyfe/hd-ble-sdk": "1.0.20-alpha.1", - "@onekeyfe/hd-core": "1.0.20-alpha.1", - "@onekeyfe/hd-shared": "1.0.20-alpha.1", - "@onekeyfe/hd-transport": "1.0.20-alpha.1", - "@onekeyfe/hd-web-sdk": "1.0.20-alpha.1", + "@onekeyfe/hd-ble-sdk": "^1.0.20-alpha.2", + "@onekeyfe/hd-core": "^1.0.20-alpha.2", + "@onekeyfe/hd-shared": "^1.0.20-alpha.2", + "@onekeyfe/hd-transport": "^1.0.20-alpha.2", + "@onekeyfe/hd-web-sdk": "^1.0.20-alpha.2", "@onekeyfe/onekey-cross-webview": "2.2.10", "@polkadot/extension-inject": "0.46.6", "@polkadot/types": "11.3.1", diff --git a/packages/components/src/actions/Popover/index.tsx b/packages/components/src/actions/Popover/index.tsx index 62c0b431545..c9c5634c7da 100644 --- a/packages/components/src/actions/Popover/index.tsx +++ b/packages/components/src/actions/Popover/index.tsx @@ -20,7 +20,7 @@ import { useKeyboardHeight, useSafeAreaInsets, } from '../../hooks'; -import { SizableText, XStack, YStack } from '../../primitives'; +import { SizableText, Stack, XStack, YStack } from '../../primitives'; import { NATIVE_HIT_SLOP } from '../../utils'; import { IconButton } from '../IconButton'; import { Trigger } from '../Trigger'; @@ -315,62 +315,50 @@ function RawPopover({ mx: 'auto', }} > - {/* header */} - - {typeof title === 'string' ? ( - - {title} - - ) : ( - title - )} - - - - {/* divider */} - {/* - - */} - - - {content} - + + {typeof title === 'string' ? ( + + {title} + + ) : ( + title + )} + + + + + {content} + + diff --git a/packages/components/src/layouts/Navigation/Header/HeaderView.tsx b/packages/components/src/layouts/Navigation/Header/HeaderView.tsx index 2961a664a02..2432b8875ec 100644 --- a/packages/components/src/layouts/Navigation/Header/HeaderView.tsx +++ b/packages/components/src/layouts/Navigation/Header/HeaderView.tsx @@ -51,6 +51,8 @@ function HeaderView({ headerStyle, headerBackground, headerShown = true, + headerRightContainerStyle = {}, + headerTitleContainerStyle = {}, // native HeaderSearchBar in packages/components/src/layouts/Page/PageHeader.tsx headerSearchBarOptions, headerTitleStyle, @@ -158,8 +160,10 @@ function HeaderView({ fontWeight: '600', ...(headerTitleStyle as any), }} + headerRightContainerStyle={headerRightContainerStyle} headerTitleContainerStyle={{ marginHorizontal: 0, + ...(headerTitleContainerStyle as any), }} headerTransparent headerBackground={headerBackground} diff --git a/packages/components/src/layouts/Navigation/ScreenProps.ts b/packages/components/src/layouts/Navigation/ScreenProps.ts index df8a87b931d..6a65db66bbc 100644 --- a/packages/components/src/layouts/Navigation/ScreenProps.ts +++ b/packages/components/src/layouts/Navigation/ScreenProps.ts @@ -7,6 +7,7 @@ import type { StackActionHelpers, StackNavigationState, } from '@react-navigation/core'; +import type { HeaderOptions } from '@react-navigation/elements'; import type { ParamListBase, Route, RouteProp } from '@react-navigation/native'; import type { HeaderButtonProps, @@ -97,7 +98,7 @@ export type IStackHeaderProps = { back?: { title: string; }; - options: IStackNavigationOptions; + options: IStackNavigationOptions & HeaderOptions; route: Route; navigation: IPageNavigationProp; }; diff --git a/packages/components/src/layouts/Navigation/Tab/TabBar/DesktopLeftSideBar.tsx b/packages/components/src/layouts/Navigation/Tab/TabBar/DesktopLeftSideBar.tsx index cc8a321a580..0aa0c4a7763 100644 --- a/packages/components/src/layouts/Navigation/Tab/TabBar/DesktopLeftSideBar.tsx +++ b/packages/components/src/layouts/Navigation/Tab/TabBar/DesktopLeftSideBar.tsx @@ -1,8 +1,7 @@ -import { useCallback, useMemo } from 'react'; +import { useMemo } from 'react'; -import { CommonActions, useNavigation } from '@react-navigation/native'; +import { CommonActions } from '@react-navigation/native'; import { MotiView } from 'moti'; -import { useIntl } from 'react-intl'; import { StyleSheet } from 'react-native'; import { getTokens, useMedia, useTheme } from 'tamagui'; @@ -14,23 +13,9 @@ import { import useProviderSideBarValue from '@onekeyhq/components/src/hocs/Provider/hooks/useProviderSideBarValue'; import { useSafeAreaInsets } from '@onekeyhq/components/src/hooks'; import type { IKeyOfIcons } from '@onekeyhq/components/src/primitives'; -import { - Icon, - Stack, - XStack, - YStack, -} from '@onekeyhq/components/src/primitives'; -import { DOWNLOAD_URL } from '@onekeyhq/shared/src/config/appConfig'; -import { ETranslations } from '@onekeyhq/shared/src/locale'; +import { Icon, XStack, YStack } from '@onekeyhq/components/src/primitives'; import platformEnv from '@onekeyhq/shared/src/platformEnv'; -import { - EModalRoutes, - EModalSettingRoutes, - ERootRoutes, -} from '@onekeyhq/shared/src/routes'; import { type EShortcutEvents } from '@onekeyhq/shared/src/shortcuts/shortcuts.enum'; -import { shortcutsKeys } from '@onekeyhq/shared/src/shortcuts/shortcutsKeys.enum'; -import { openUrlExternal } from '@onekeyhq/shared/src/utils/openUrlUtils'; import { DesktopDragZoneAbsoluteBar } from '../../../DesktopDragZoneBox'; @@ -87,26 +72,6 @@ function TabItemView({ return contentMemo; } -function DownloadButton() { - const intl = useIntl(); - const onPress = useCallback(() => { - openUrlExternal(DOWNLOAD_URL); - }, []); - if (!platformEnv.isWeb) { - return null; - } - return ( - - ); -} - function OneKeyLogo() { if (!platformEnv.isWeb) { return null; @@ -127,7 +92,6 @@ export function DesktopLeftSideBar({ extraConfig?: ITabNavigatorExtraConfig; }) { const { routes } = state; - const intl = useIntl(); const { leftSidebarCollapsed: isCollapse } = useProviderSideBarValue(); const { top } = useSafeAreaInsets(); // used for ipad const theme = useTheme(); @@ -192,15 +156,6 @@ export function DesktopLeftSideBar({ ], ); - const appNavigation = useNavigation(); - const openSettingPage = useCallback(() => { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - appNavigation.navigate(ERootRoutes.Modal, { - screen: EModalRoutes.SettingModal, - params: EModalSettingRoutes.SettingListModal, - }); - }, [appNavigation]); - return ( {tabs} - - - - - + diff --git a/packages/kit-bg/src/services/ServiceAccount/ServiceAccount.ts b/packages/kit-bg/src/services/ServiceAccount/ServiceAccount.ts index 4f56eb45259..b06ca73cd92 100644 --- a/packages/kit-bg/src/services/ServiceAccount/ServiceAccount.ts +++ b/packages/kit-bg/src/services/ServiceAccount/ServiceAccount.ts @@ -70,6 +70,7 @@ import timerUtils from '@onekeyhq/shared/src/utils/timerUtils'; import type { IServerNetwork } from '@onekeyhq/shared/types'; import type { IBatchCreateAccount, + IHwQrWalletWithDevice, INetworkAccount, } from '@onekeyhq/shared/types/account'; import type { IGeneralInputValidation } from '@onekeyhq/shared/types/address'; @@ -271,6 +272,36 @@ class ServiceAccount extends ServiceBase { }; } + @backgroundMethod() + async getAllHwQrWalletWithDevice() { + const { wallets, allDevices } = await this.getAllWallets({ + refillWalletInfo: true, + }); + // const { devices } = await this.getAllDevices(); + + const result: { + [walletId: string]: IHwQrWalletWithDevice; + } = {}; + + for (const wallet of wallets) { + if ( + !accountUtils.isHwHiddenWallet({ wallet }) && + (accountUtils.isHwWallet({ walletId: wallet.id }) || + accountUtils.isQrWallet({ walletId: wallet.id })) + ) { + const device = (allDevices ?? []).find( + (d) => d.id === wallet.associatedDevice, + ); + result[wallet.id] = { + wallet, + device, + }; + } + } + + return result; + } + @backgroundMethod() async isWalletHasIndexedAccounts({ walletId }: { walletId: string }) { const { accounts: indexedAccounts } = await this.getIndexedAccountsOfWallet( diff --git a/packages/kit/assets/device-management-guide.png b/packages/kit/assets/device-management-guide.png new file mode 100644 index 00000000000..32b738b825b Binary files /dev/null and b/packages/kit/assets/device-management-guide.png differ diff --git a/packages/kit/src/components/TabPageHeader/HeaderRight.tsx b/packages/kit/src/components/TabPageHeader/HeaderRight.tsx index 3a0b167956a..ec7c5fe142d 100644 --- a/packages/kit/src/components/TabPageHeader/HeaderRight.tsx +++ b/packages/kit/src/components/TabPageHeader/HeaderRight.tsx @@ -3,15 +3,7 @@ import { useCallback, useMemo } from 'react'; import { useIntl } from 'react-intl'; -import { - ActionList, - Shortcut, - SizableText, - Stack, - Tooltip, - XStack, - useMedia, -} from '@onekeyhq/components'; +import { ActionList, SizableText, Stack, useMedia } from '@onekeyhq/components'; import { HeaderButtonGroup, HeaderIconButton, @@ -28,9 +20,8 @@ import { import { ETranslations } from '@onekeyhq/shared/src/locale'; import { defaultLogger } from '@onekeyhq/shared/src/logger/logger'; import platformEnv from '@onekeyhq/shared/src/platformEnv'; -import { EModalRoutes, EModalSettingRoutes } from '@onekeyhq/shared/src/routes'; +import { EModalRoutes } from '@onekeyhq/shared/src/routes'; import { EModalNotificationsRoutes } from '@onekeyhq/shared/src/routes/notifications'; -import { shortcutsKeys } from '@onekeyhq/shared/src/shortcuts/shortcutsKeys.enum'; import extUtils from '@onekeyhq/shared/src/utils/extUtils'; import { EAccountSelectorSceneName } from '@onekeyhq/shared/types'; @@ -40,6 +31,7 @@ import { UrlAccountNavHeader } from '../../views/Home/pages/urlAccount/UrlAccoun import { PrimeHeaderIconButton } from '../../views/Prime/components/PrimeHeaderIconButton'; import useScanQrCode from '../../views/ScanQrCode/hooks/useScanQrCode'; +import { MoreActionButton } from './MoreActionButton'; import { UniversalSearchInput } from './UniversalSearchInput'; export function HeaderRight({ @@ -58,11 +50,6 @@ export function HeaderRight({ } = useActiveAccount({ num: 0 }); const [allTokens] = useAllTokenListAtom(); const [map] = useAllTokenListMapAtom(); - const openSettingPage = useCallback(() => { - navigation.pushModal(EModalRoutes.SettingModal, { - screen: EModalSettingRoutes.SettingListModal, - }); - }, [navigation]); const onScanButtonPressed = useCallback( () => scanQrCode.start({ @@ -86,27 +73,6 @@ export function HeaderRight({ }, [navigation]); const items = useMemo(() => { - const settingsButton = media.gtMd ? null : ( - - - {intl.formatMessage({ id: ETranslations.settings_settings })} - - - {shortcutsKeys.CmdOrCtrl} - , - - - } - titlePlacement="bottom" - icon="SettingsOutline" - testID="setting" - onPress={openSettingPage} - /> - ); - const routeInfo = { routes: '', }; @@ -163,14 +129,15 @@ export function HeaderRight({ } /> ); - const scanButton = ( + + const scanButton = media.gtMd ? ( - ); + ) : null; // const primeButton = // devSettings?.enabled && devSettings?.settings?.showPrimeTest ? ( // @@ -230,6 +197,11 @@ export function HeaderRight({ ) : null} ); + + const moreActionButton = media.gtMd ? null : ( + + ); + const searchInput = media.gtMd ? ( ) : null; @@ -248,7 +220,7 @@ export function HeaderRight({ layoutExtView, primeButton, notificationsButton, - settingsButton, + moreActionButton, ].filter(Boolean); } @@ -258,16 +230,15 @@ export function HeaderRight({ } return [ - scanButton, primeButton, + scanButton, notificationsButton, - settingsButton, + moreActionButton, searchInput, ].filter(Boolean); }, [ media.gtMd, intl, - openSettingPage, onScanButtonPressed, devSettings.enabled, openNotificationsModal, diff --git a/packages/kit/src/components/TabPageHeader/MoreActionButton.tsx b/packages/kit/src/components/TabPageHeader/MoreActionButton.tsx new file mode 100644 index 00000000000..36a1b01979d --- /dev/null +++ b/packages/kit/src/components/TabPageHeader/MoreActionButton.tsx @@ -0,0 +1,131 @@ +import { useCallback } from 'react'; + +import { useIntl } from 'react-intl'; + +import { ActionList, HeaderIconButton } from '@onekeyhq/components'; +import useAppNavigation from '@onekeyhq/kit/src/hooks/useAppNavigation'; +import { useShowAddressBook } from '@onekeyhq/kit/src/hooks/useShowAddressBook'; +import { useActiveAccount } from '@onekeyhq/kit/src/states/jotai/contexts/accountSelector'; +import { + useAllTokenListAtom, + useAllTokenListMapAtom, +} from '@onekeyhq/kit/src/states/jotai/contexts/tokenList'; +import { ETranslations } from '@onekeyhq/shared/src/locale'; +import { + EModalDeviceManagementRoutes, + EModalRoutes, + EModalSettingRoutes, + EOnboardingPages, +} from '@onekeyhq/shared/src/routes'; + +import backgroundApiProxy from '../../background/instance/backgroundApiProxy'; +import useScanQrCode from '../../views/ScanQrCode/hooks/useScanQrCode'; + +export function MoreActionButton() { + const intl = useIntl(); + const navigation = useAppNavigation(); + const scanQrCode = useScanQrCode(); + const { + activeAccount: { account }, + } = useActiveAccount({ num: 0 }); + const [allTokens] = useAllTokenListAtom(); + const [map] = useAllTokenListMapAtom(); + const openAddressBook = useShowAddressBook({ + useNewModal: true, + }); + + const handleScan = useCallback( + async (close: () => void) => { + close(); + await scanQrCode.start({ + handlers: scanQrCode.PARSE_HANDLER_NAMES.all, + autoHandleResult: true, + account, + tokens: { + data: allTokens.tokens, + keys: allTokens.keys, + map, + }, + }); + }, + [scanQrCode, account, allTokens, map], + ); + + const handleSettings = useCallback( + (close: () => void) => { + close(); + navigation.pushModal(EModalRoutes.SettingModal, { + screen: EModalSettingRoutes.SettingListModal, + }); + }, + [navigation], + ); + + const handleDeviceManagement = useCallback( + async (close: () => void) => { + close(); + try { + const allHwQrWallet = + await backgroundApiProxy.serviceAccount.getAllHwQrWalletWithDevice(); + if (Object.keys(allHwQrWallet).length > 0) { + navigation.pushModal(EModalRoutes.DeviceManagementModal, { + screen: EModalDeviceManagementRoutes.DeviceListModal, + }); + return; + } + + navigation.pushModal(EModalRoutes.OnboardingModal, { + screen: EOnboardingPages.DeviceManagementGuide, + }); + } catch (error) { + console.error('Failed to handle device management:', error); + } + }, + [navigation], + ); + + const handleAddressBook = useCallback( + (close: () => void) => { + close(); + void openAddressBook(); + }, + [openAddressBook], + ); + + return ( + + } + items={[ + { + label: intl.formatMessage({ id: ETranslations.global_my_onekey }), + icon: 'PhoneOutline', + onPress: handleDeviceManagement, + testID: 'my-onekey', + }, + { + label: intl.formatMessage({ id: ETranslations.scan_scan_qr_code }), + icon: 'ScanOutline', + onPress: handleScan, + }, + { + label: intl.formatMessage({ id: ETranslations.address_book_title }), + icon: 'BookOpenOutline', + onPress: handleAddressBook, + testID: 'address-book', + }, + { + label: intl.formatMessage({ id: ETranslations.settings_settings }), + icon: 'SettingsOutline', + onPress: handleSettings, + }, + ]} + /> + ); +} diff --git a/packages/kit/src/hooks/useShowAddressBook.ts b/packages/kit/src/hooks/useShowAddressBook.ts new file mode 100644 index 00000000000..d844eab767a --- /dev/null +++ b/packages/kit/src/hooks/useShowAddressBook.ts @@ -0,0 +1,50 @@ +import { useCallback } from 'react'; + +import { useIntl } from 'react-intl'; + +import { useAddressBookPersistAtom } from '@onekeyhq/kit-bg/src/states/jotai/atoms'; +import { defaultLogger } from '@onekeyhq/shared/src/logger/logger'; +import { + EModalAddressBookRoutes, + EModalRoutes, +} from '@onekeyhq/shared/src/routes'; + +import backgroundApiProxy from '../background/instance/backgroundApiProxy'; +import { showAddressSafeNotificationDialog } from '../components/AddressInput/AddressSafeDialog'; + +import useAppNavigation from './useAppNavigation'; + +export function useShowAddressBook({ + useNewModal = false, +}: { + useNewModal?: boolean; +}) { + const intl = useIntl(); + const navigation = useAppNavigation(); + const [{ hideDialogInfo }] = useAddressBookPersistAtom(); + + const showAddressBook = useCallback(async () => { + await backgroundApiProxy.servicePassword.promptPasswordVerify(); + if (useNewModal) { + navigation.pushModal(EModalRoutes.AddressBookModal, { + screen: EModalAddressBookRoutes.ListItemModal, + params: {}, + }); + } else { + navigation.push(EModalAddressBookRoutes.ListItemModal); + } + defaultLogger.setting.page.enterAddressBook(); + }, [navigation, useNewModal]); + + const onPress = useCallback(async () => { + if (!hideDialogInfo) { + await showAddressSafeNotificationDialog({ + intl, + }); + await backgroundApiProxy.serviceAddressBook.hideDialogInfo(); + } + await showAddressBook(); + }, [hideDialogInfo, showAddressBook, intl]); + + return onPress; +} diff --git a/packages/kit/src/provider/Container/PortalBodyContainer/SideBanner.tsx b/packages/kit/src/provider/Container/PortalBodyContainer/SideBanner.tsx index d4bed74eea1..9026aa4f56f 100644 --- a/packages/kit/src/provider/Container/PortalBodyContainer/SideBanner.tsx +++ b/packages/kit/src/provider/Container/PortalBodyContainer/SideBanner.tsx @@ -1,6 +1,7 @@ import { useCallback } from 'react'; import { useIntl } from 'react-intl'; +import { StyleSheet } from 'react-native'; import { EPortalContainerConstantName, @@ -12,12 +13,26 @@ import { Stack, useMedia, } from '@onekeyhq/components'; +import { DesktopTabItem } from '@onekeyhq/components/src/layouts/Navigation/Tab/TabBar/DesktopTabItem'; import SidebarBannerImage from '@onekeyhq/kit/assets/sidebar-banner.png'; import { useSpotlight } from '@onekeyhq/kit/src/components/Spotlight'; +import useAppNavigation from '@onekeyhq/kit/src/hooks/useAppNavigation'; +import { useShowAddressBook } from '@onekeyhq/kit/src/hooks/useShowAddressBook'; +import { DOWNLOAD_URL } from '@onekeyhq/shared/src/config/appConfig'; import { ETranslations } from '@onekeyhq/shared/src/locale'; +import platformEnv from '@onekeyhq/shared/src/platformEnv'; +import { + EModalDeviceManagementRoutes, + EModalRoutes, + EModalSettingRoutes, + EOnboardingPages, +} from '@onekeyhq/shared/src/routes'; +import { shortcutsKeys } from '@onekeyhq/shared/src/shortcuts/shortcutsKeys.enum'; import { ESpotlightTour } from '@onekeyhq/shared/src/spotlight'; import { openUrlExternal } from '@onekeyhq/shared/src/utils/openUrlUtils'; +import backgroundApiProxy from '../../../background/instance/backgroundApiProxy'; + import type { GestureResponderEvent } from 'react-native'; function BasicSidebarBanner() { @@ -85,11 +100,103 @@ function BasicSidebarBanner() { ) : null; } +function DownloadButton() { + const intl = useIntl(); + const onPress = useCallback(() => { + openUrlExternal(DOWNLOAD_URL); + }, []); + + if (!platformEnv.isWeb) { + return null; + } + + return ( + + ); +} + +function BottomMenu() { + const intl = useIntl(); + const appNavigation = useAppNavigation(); + + const openSettingPage = useCallback(() => { + appNavigation.pushModal(EModalRoutes.SettingModal, { + screen: EModalSettingRoutes.SettingListModal, + }); + }, [appNavigation]); + + const openAddressBookPage = useShowAddressBook({ + useNewModal: true, + }); + + const openDeviceManagementPage = useCallback(async () => { + const allHwQrWallet = + await backgroundApiProxy.serviceAccount.getAllHwQrWalletWithDevice(); + if (Object.keys(allHwQrWallet).length > 0) { + appNavigation.pushModal(EModalRoutes.DeviceManagementModal, { + screen: EModalDeviceManagementRoutes.DeviceListModal, + }); + return; + } + + appNavigation.pushModal(EModalRoutes.OnboardingModal, { + screen: EOnboardingPages.DeviceManagementGuide, + }); + }, [appNavigation]); + + return ( + + + + + + + + ); +} + export const SidebarBanner = () => { const { gtMd } = useMedia(); return gtMd ? ( - + ) : null; }; diff --git a/packages/kit/src/routes/Modal/router.tsx b/packages/kit/src/routes/Modal/router.tsx index f06696022cd..c765ef9a94c 100644 --- a/packages/kit/src/routes/Modal/router.tsx +++ b/packages/kit/src/routes/Modal/router.tsx @@ -12,6 +12,7 @@ import { AssetSelectorRouter } from '../../views/AssetSelector/router'; import { ChainSelectorRouter } from '../../views/ChainSelector/router'; import { CloudBackupPages } from '../../views/CloudBackup/router'; import { DAppConnectionRouter } from '../../views/DAppConnection/router'; +import { DeviceManagementStacks } from '../../views/DeviceManagement/router'; import { ModalDiscoveryStack } from '../../views/Discovery/router'; import { ModalFiatCryptoRouter } from '../../views/FiatCrypto/router'; import { ModalFirmwareUpdateStack } from '../../views/FirmwareUpdate/router'; @@ -163,6 +164,10 @@ const router: IModalRootNavigatorConfig[] = [ name: EModalRoutes.ShortcutsModal, children: ShortcutsModalRouter, }, + { + name: EModalRoutes.DeviceManagementModal, + children: DeviceManagementStacks, + }, ]; // Pages in Dev Mode diff --git a/packages/kit/src/views/AccountManagerStacks/pages/AccountSelectorStack/WalletDetails/WalletOptions/DeviceManagementButton.tsx b/packages/kit/src/views/AccountManagerStacks/pages/AccountSelectorStack/WalletDetails/WalletOptions/DeviceManagementButton.tsx new file mode 100644 index 00000000000..c75b3aaaf04 --- /dev/null +++ b/packages/kit/src/views/AccountManagerStacks/pages/AccountSelectorStack/WalletDetails/WalletOptions/DeviceManagementButton.tsx @@ -0,0 +1,58 @@ +import { useIntl } from 'react-intl'; + +import backgroundApiProxy from '@onekeyhq/kit/src/background/instance/backgroundApiProxy'; +import { AccountSelectorProviderMirror } from '@onekeyhq/kit/src/components/AccountSelector'; +import useAppNavigation from '@onekeyhq/kit/src/hooks/useAppNavigation'; +import { useActiveAccount } from '@onekeyhq/kit/src/states/jotai/contexts/accountSelector'; +import type { IDBWallet } from '@onekeyhq/kit-bg/src/dbs/local/types'; +import { ETranslations } from '@onekeyhq/shared/src/locale'; +import { + EModalDeviceManagementRoutes, + EModalRoutes, +} from '@onekeyhq/shared/src/routes'; +import networkUtils from '@onekeyhq/shared/src/utils/networkUtils'; +import { EAccountSelectorSceneName } from '@onekeyhq/shared/types'; + +import { WalletOptionItem } from './WalletOptionItem'; + +function DeviceManagementButtonView({ + wallet, +}: { + wallet: IDBWallet | undefined; +}) { + const intl = useIntl(); + const navigation = useAppNavigation(); + + return ( + { + navigation.pushModal(EModalRoutes.DeviceManagementModal, { + screen: EModalDeviceManagementRoutes.DeviceDetailModal, + params: { + walletId: wallet?.id || '', + }, + }); + }} + /> + ); +} + +export function DeviceManagementButton({ + wallet, +}: { + wallet: IDBWallet | undefined; +}) { + return ( + + + + ); +} diff --git a/packages/kit/src/views/AccountManagerStacks/pages/AccountSelectorStack/WalletDetails/WalletOptions/index.tsx b/packages/kit/src/views/AccountManagerStacks/pages/AccountSelectorStack/WalletDetails/WalletOptions/index.tsx index f073f16e41d..7249c38aeb2 100644 --- a/packages/kit/src/views/AccountManagerStacks/pages/AccountSelectorStack/WalletDetails/WalletOptions/index.tsx +++ b/packages/kit/src/views/AccountManagerStacks/pages/AccountSelectorStack/WalletDetails/WalletOptions/index.tsx @@ -6,20 +6,17 @@ import { HiddenWalletAddButton } from '@onekeyhq/kit/src/views/AccountManagerSta import { defaultLogger } from '@onekeyhq/shared/src/logger/logger'; import accountUtils from '@onekeyhq/shared/src/utils/accountUtils'; -import { Advance } from './Advance'; import { BatchCreateAccountButton } from './BatchCreateAccountButton'; -import { CheckFirmwareUpdateButton } from './CheckFirmwareUpdateButton'; -import { HardwareHomeScreenButton } from './HardwareHomeScreenButton'; +import { DeviceManagementButton } from './DeviceManagementButton'; import { HdWalletBackupButton } from './HdWalletBackupButton'; import { HiddenWalletRememberSwitch } from './HiddenWalletRememberSwitch'; -import { Verification } from './Verification'; import { WalletProfile } from './WalletProfile'; import type { IWalletDetailsProps } from '..'; type IWalletOptionsProps = Partial; -function WalletOptionsView({ wallet, device }: IWalletOptionsProps) { +function WalletOptionsView({ wallet }: IWalletOptionsProps) { const [editMode] = useAccountSelectorEditModeAtom(); const walletSpecifiedOptions = useMemo(() => { @@ -48,10 +45,11 @@ function WalletOptionsView({ wallet, device }: IWalletOptionsProps) { // HW Normal Wallet return ( <> - + {/* - + */} + @@ -77,7 +75,7 @@ function WalletOptionsView({ wallet, device }: IWalletOptionsProps) { } return null; - }, [device, wallet]); + }, [wallet]); return ( // diff --git a/packages/kit/src/views/DeviceManagement/hooks/useBuyOneKeyHeaderRightButton.tsx b/packages/kit/src/views/DeviceManagement/hooks/useBuyOneKeyHeaderRightButton.tsx new file mode 100644 index 00000000000..7f2f39e5a13 --- /dev/null +++ b/packages/kit/src/views/DeviceManagement/hooks/useBuyOneKeyHeaderRightButton.tsx @@ -0,0 +1,34 @@ +import { useCallback } from 'react'; + +import { HeaderIconButton } from '@onekeyhq/components/src/layouts/Navigation/Header'; +import useAppNavigation from '@onekeyhq/kit/src/hooks/useAppNavigation'; +import { EOnboardingPages } from '@onekeyhq/shared/src/routes'; +import { EModalDeviceManagementRoutes } from '@onekeyhq/shared/src/routes/deviceManagement'; + +export function useBuyOneKeyHeaderRightButton( + params?: + | { + inDeviceManagementStack?: boolean; + } + | undefined, +) { + const navigation = useAppNavigation(); + + const toOneKeyHardwareWalletPage = useCallback(() => { + if (params?.inDeviceManagementStack) { + navigation.push(EModalDeviceManagementRoutes.BuyOneKeyHardwareWallet); + } else { + navigation.push(EOnboardingPages.OneKeyHardwareWallet); + } + }, [params?.inDeviceManagementStack, navigation]); + + return { + headerRight: () => ( + + ), + toOneKeyHardwareWalletPage, + }; +} diff --git a/packages/kit/src/views/DeviceManagement/pages/DeviceDetailsModal/DeviceAdvanceSection.tsx b/packages/kit/src/views/DeviceManagement/pages/DeviceDetailsModal/DeviceAdvanceSection.tsx new file mode 100644 index 00000000000..a80de810a9b --- /dev/null +++ b/packages/kit/src/views/DeviceManagement/pages/DeviceDetailsModal/DeviceAdvanceSection.tsx @@ -0,0 +1,68 @@ +import { useIntl } from 'react-intl'; + +import { SizableText, Switch, XStack, YStack } from '@onekeyhq/components'; +import { ListItem } from '@onekeyhq/kit/src/components/ListItem'; +import { ETranslations } from '@onekeyhq/shared/src/locale'; + +function DeviceAdvanceSection({ + passphraseEnabled, + pinOnAppEnabled, + onPassphraseEnabledChange, + onPinOnAppEnabledChange, + inputPinOnSoftwareSupport, +}: { + passphraseEnabled: boolean; + pinOnAppEnabled: boolean; + onPassphraseEnabledChange: (value: boolean) => void; + onPinOnAppEnabledChange: (value: boolean) => void; + inputPinOnSoftwareSupport: boolean; +}) { + const intl = useIntl(); + return ( + + + + {intl.formatMessage({ + id: ETranslations.global_advance, + })} + + + + + { + onPassphraseEnabledChange(!passphraseEnabled); + }} + /> + + {inputPinOnSoftwareSupport ? ( + + { + onPinOnAppEnabledChange(!pinOnAppEnabled); + }} + /> + + ) : null} + + + ); +} + +export default DeviceAdvanceSection; diff --git a/packages/kit/src/views/DeviceManagement/pages/DeviceDetailsModal/DeviceBasicInfoSection.tsx b/packages/kit/src/views/DeviceManagement/pages/DeviceDetailsModal/DeviceBasicInfoSection.tsx new file mode 100644 index 00000000000..e918d2ebae5 --- /dev/null +++ b/packages/kit/src/views/DeviceManagement/pages/DeviceDetailsModal/DeviceBasicInfoSection.tsx @@ -0,0 +1,157 @@ +import { useMemo } from 'react'; + +import { useIntl } from 'react-intl'; + +import type { IBadgeType, IIconProps, IKeyOfIcons } from '@onekeyhq/components'; +import { Badge, Icon, SizableText, XStack, YStack } from '@onekeyhq/components'; +import { ListItem } from '@onekeyhq/kit/src/components/ListItem'; +import { WalletAvatar } from '@onekeyhq/kit/src/components/WalletAvatar'; +import { usePromiseResult } from '@onekeyhq/kit/src/hooks/usePromiseResult'; +import { WalletRenameButton } from '@onekeyhq/kit/src/views/AccountManagerStacks/components/WalletRename'; +import { ETranslations } from '@onekeyhq/shared/src/locale'; +import accountUtils from '@onekeyhq/shared/src/utils/accountUtils'; +import deviceUtils from '@onekeyhq/shared/src/utils/deviceUtils'; +import type { IHwQrWalletWithDevice } from '@onekeyhq/shared/types/account'; + +function DeviceBasicInfoSection({ + data, + onPressHomescreen, + onPressAuthRequest, + onPressCheckForUpdates, +}: { + data: IHwQrWalletWithDevice; + onPressHomescreen: () => void; + onPressAuthRequest: () => void; + onPressCheckForUpdates: () => void; +}) { + const { wallet, device } = data; + const intl = useIntl(); + const isQrWallet = accountUtils.isQrWallet({ walletId: wallet.id }); + + const defaultInfo = useMemo( + () => ({ + firmwareVersion: '-', + walletAvatarBadge: isQrWallet ? 'QR' : undefined, + verifiedBadgeType: 'default' as IBadgeType, + verifiedBadgeText: '-', + verifiedBadgeTextColor: '$iconCritical' as IIconProps['color'], + verifiedBadgeIconName: 'ErrorSolid' as IKeyOfIcons, + verifiedBadgeIconColor: '$iconCritical' as IIconProps['color'], + }), + [isQrWallet], + ); + + const { result: deviceInfo } = usePromiseResult( + async () => { + if (!device?.featuresInfo) { + return defaultInfo; + } + + const versions = await deviceUtils.getDeviceVersion({ + device, + features: device.featuresInfo, + }); + + const isVerified = Boolean(device.verifiedAtVersion); + const verificationStatus = { + success: { + type: 'success' as IBadgeType, + icon: 'BadgeVerifiedSolid' as IKeyOfIcons, + color: '$iconSuccess' as IIconProps['color'], + textId: ETranslations.global_verified, + }, + critical: { + type: 'critical' as IBadgeType, + icon: 'ErrorSolid' as IKeyOfIcons, + color: '$iconCritical' as IIconProps['color'], + textId: ETranslations.global_unofficial, + }, + }; + + const status = isVerified + ? verificationStatus.success + : verificationStatus.critical; + + return { + firmwareVersion: versions?.firmwareVersion ?? '-', + walletAvatarBadge: isQrWallet ? 'QR' : undefined, + verifiedBadgeType: status.type, + verifiedBadgeIconName: status.icon, + verifiedBadgeIconColor: status.color, + verifiedBadgeText: intl.formatMessage({ id: status.textId }), + verifiedBadgeTextColor: status.color, + }; + }, + [device, isQrWallet, intl, defaultInfo], + { initResult: defaultInfo }, + ); + + return ( + + + + + + + + + + {isQrWallet ? null : ( + + + {`v${deviceInfo.firmwareVersion}`} + + + + + + {deviceInfo.verifiedBadgeText} + + + + + )} + + + {isQrWallet ? null : ( + + + + + + )} + + ); +} + +export default DeviceBasicInfoSection; diff --git a/packages/kit/src/views/DeviceManagement/pages/DeviceDetailsModal/DeviceQrInfoSection.tsx b/packages/kit/src/views/DeviceManagement/pages/DeviceDetailsModal/DeviceQrInfoSection.tsx new file mode 100644 index 00000000000..8f1d8fd9bbf --- /dev/null +++ b/packages/kit/src/views/DeviceManagement/pages/DeviceDetailsModal/DeviceQrInfoSection.tsx @@ -0,0 +1,39 @@ +import { useIntl } from 'react-intl'; + +import { SizableText, YStack } from '@onekeyhq/components'; +import { ETranslations } from '@onekeyhq/shared/src/locale'; + +function DeviceQrInfoSection() { + const intl = useIntl(); + + return ( + + + + {intl.formatMessage({ + id: ETranslations.global_about_qr_details_question_a, + })} + + + {intl.formatMessage({ + id: ETranslations.global_about_qr_details_answer_a, + })} + + + + + {intl.formatMessage({ + id: ETranslations.global_about_qr_details_question_b, + })} + + + {intl.formatMessage({ + id: ETranslations.global_about_qr_details_answer_b, + })} + + + + ); +} + +export default DeviceQrInfoSection; diff --git a/packages/kit/src/views/DeviceManagement/pages/DeviceDetailsModal/DeviceSpecsSection.tsx b/packages/kit/src/views/DeviceManagement/pages/DeviceDetailsModal/DeviceSpecsSection.tsx new file mode 100644 index 00000000000..45e475adcab --- /dev/null +++ b/packages/kit/src/views/DeviceManagement/pages/DeviceDetailsModal/DeviceSpecsSection.tsx @@ -0,0 +1,122 @@ +import { useMemo } from 'react'; + +import { useIntl } from 'react-intl'; + +import { SizableText, XStack, YStack } from '@onekeyhq/components'; +import { usePromiseResult } from '@onekeyhq/kit/src/hooks/usePromiseResult'; +import { ETranslations } from '@onekeyhq/shared/src/locale'; +import deviceUtils from '@onekeyhq/shared/src/utils/deviceUtils'; +import type { IHwQrWalletWithDevice } from '@onekeyhq/shared/types/account'; + +type ISpecItemProps = { + title: string; + value: string; +}; + +function SpecItem({ title, value }: ISpecItemProps) { + return ( + + + {title} + + + {value} + + + ); +} + +function DeviceSpecsSection({ data }: { data: IHwQrWalletWithDevice }) { + const intl = useIntl(); + const { device } = data; + const defaultDeviceInfo = useMemo( + () => ({ + model: '-', + bleName: '-', + bleVersion: '-', + bootloaderVersion: '-', + firmwareVersion: '-', + serialNumber: '-', + }), + [], + ); + const { result: deviceInfo } = usePromiseResult( + async () => { + if (!device || !device.featuresInfo) { + return defaultDeviceInfo; + } + + const versions = await deviceUtils.getDeviceVersion({ + device, + features: device.featuresInfo, + }); + + const model = await deviceUtils.buildDeviceLabel({ + features: device.featuresInfo, + buildModelName: true, + }); + + return { + model, + bleName: device.featuresInfo.ble_name ?? '-', + bleVersion: versions?.bleVersion ?? '-', + bootloaderVersion: versions?.bootloaderVersion ?? '-', + firmwareVersion: versions?.firmwareVersion ?? '-', + serialNumber: + device.featuresInfo.onekey_serial ?? + device.featuresInfo.serial_no ?? + '-', + }; + }, + [device, defaultDeviceInfo], + { + initResult: defaultDeviceInfo, + }, + ); + + return ( + + + + {intl.formatMessage({ + id: ETranslations.global_device_info, + })} + + + + + + + + + + + ); +} + +export default DeviceSpecsSection; diff --git a/packages/kit/src/views/DeviceManagement/pages/DeviceDetailsModal/index.tsx b/packages/kit/src/views/DeviceManagement/pages/DeviceDetailsModal/index.tsx new file mode 100644 index 00000000000..ad8dd0f1417 --- /dev/null +++ b/packages/kit/src/views/DeviceManagement/pages/DeviceDetailsModal/index.tsx @@ -0,0 +1,202 @@ +import { useCallback, useEffect, useState } from 'react'; + +import { useRoute } from '@react-navigation/native'; +import { useIntl } from 'react-intl'; + +import { Page, YStack } from '@onekeyhq/components'; +import backgroundApiProxy from '@onekeyhq/kit/src/background/instance/backgroundApiProxy'; +import useAppNavigation from '@onekeyhq/kit/src/hooks/useAppNavigation'; +import { usePromiseResult } from '@onekeyhq/kit/src/hooks/usePromiseResult'; +import { useFirmwareUpdateActions } from '@onekeyhq/kit/src/views/FirmwareUpdate/hooks/useFirmwareUpdateActions'; +import { useFirmwareVerifyDialog } from '@onekeyhq/kit/src/views/Onboarding/pages/ConnectHardwareWallet/FirmwareVerifyDialog'; +import { + EAppEventBusNames, + appEventBus, +} from '@onekeyhq/shared/src/eventBus/appEventBus'; +import { ETranslations } from '@onekeyhq/shared/src/locale'; +import type { + EModalDeviceManagementRoutes, + IModalDeviceManagementParamList, +} from '@onekeyhq/shared/src/routes'; +import { + EAccountManagerStacksRoutes, + EModalRoutes, +} from '@onekeyhq/shared/src/routes'; +import accountUtils from '@onekeyhq/shared/src/utils/accountUtils'; +import type { IHwQrWalletWithDevice } from '@onekeyhq/shared/types/account'; + +import DeviceAdvanceSection from './DeviceAdvanceSection'; +import DeviceBasicInfoSection from './DeviceBasicInfoSection'; +import DeviceQrInfoSection from './DeviceQrInfoSection'; +import DeviceSpecsSection from './DeviceSpecsSection'; + +import type { RouteProp } from '@react-navigation/native'; + +function DeviceDetailsModal() { + const intl = useIntl(); + const navigation = useAppNavigation(); + const route = + useRoute< + RouteProp< + IModalDeviceManagementParamList, + EModalDeviceManagementRoutes.DeviceDetailModal + > + >(); + const { walletId } = route.params; + + const [passphraseEnabled, setPassphraseEnabled] = useState(false); + const [pinOnAppEnabled, setPinOnAppEnabled] = useState(false); + const { + result, + isLoading, + run: refreshData, + } = usePromiseResult(async () => { + const r = + await backgroundApiProxy.serviceAccount.getAllHwQrWalletWithDevice(); + + const device = r?.[walletId]?.device; + setPassphraseEnabled(Boolean(device?.featuresInfo?.passphrase_protection)); + setPinOnAppEnabled(Boolean(device?.settings?.inputPinOnSoftware)); + + return r?.[walletId] ?? undefined; + }, [walletId]); + + useEffect(() => { + const fn = () => { + void refreshData(); + }; + appEventBus.on(EAppEventBusNames.WalletUpdate, fn); + return () => { + appEventBus.off(EAppEventBusNames.WalletUpdate, fn); + }; + }, [refreshData]); + + const isQrWallet = result + ? accountUtils.isQrWallet({ walletId: result.wallet.id }) + : false; + + // Basic Info Section + const onPressHomescreen = useCallback(() => { + if (!result?.device) return; + navigation.pushModal(EModalRoutes.AccountManagerStacks, { + screen: EAccountManagerStacksRoutes.HardwareHomeScreenModal, + params: { + device: result?.device, + }, + }); + }, [result?.device, navigation]); + + const { showFirmwareVerifyDialog } = useFirmwareVerifyDialog(); + const onPressAuthRequest = useCallback(async () => { + if (!result?.device) { + return; + } + await showFirmwareVerifyDialog({ + device: result.device, + features: result.device.featuresInfo, + onContinue: async ({ checked }) => { + console.log(checked); + }, + }); + }, [result?.device, showFirmwareVerifyDialog]); + + const actions = useFirmwareUpdateActions(); + const onPressCheckForUpdates = useCallback(() => { + actions.openChangeLogModal({ + connectId: result?.device?.connectId, + }); + }, [result?.device?.connectId, actions]); + + // Advance Section + const inputPinOnSoftwareSupport = ['classic', 'mini', 'classic1s'].includes( + result?.device?.deviceType || '', + ); + + const onPassphraseEnabledChange = useCallback( + async (value: boolean) => { + try { + await backgroundApiProxy.serviceHardware.setPassphraseEnabled({ + walletId: result?.wallet.id || '', + passphraseEnabled: value, + }); + setPassphraseEnabled(value); + } catch (error) { + console.error(error); + } + }, + [result?.wallet.id], + ); + + const onPinOnAppEnabledChange = useCallback( + async (value: boolean) => { + try { + setPinOnAppEnabled(value); + await backgroundApiProxy.serviceHardware.setInputPinOnSoftware({ + walletId: result?.wallet.id || '', + inputPinOnSoftware: value, + }); + } catch (error) { + console.error(error); + setPinOnAppEnabled(!value); + } + }, + [result?.wallet.id], + ); + + const renderContent = useCallback(() => { + if (isLoading || !result) { + return null; + } + + if (isQrWallet) { + return ; + } + + return ( + <> + + + + ); + }, [ + isLoading, + result, + isQrWallet, + passphraseEnabled, + pinOnAppEnabled, + inputPinOnSoftwareSupport, + onPassphraseEnabledChange, + onPinOnAppEnabledChange, + ]); + + return ( + + + + + {result ? ( + <> + + {renderContent()} + + ) : null} + + + + ); +} + +export default DeviceDetailsModal; diff --git a/packages/kit/src/views/DeviceManagement/pages/DeviceGuideModal/index.tsx b/packages/kit/src/views/DeviceManagement/pages/DeviceGuideModal/index.tsx new file mode 100644 index 00000000000..9be91ddb117 --- /dev/null +++ b/packages/kit/src/views/DeviceManagement/pages/DeviceGuideModal/index.tsx @@ -0,0 +1,69 @@ +import { useCallback } from 'react'; + +import { useIntl } from 'react-intl'; + +import { Button, Image, Page, SizableText, YStack } from '@onekeyhq/components'; +import useAppNavigation from '@onekeyhq/kit/src/hooks/useAppNavigation'; +import { ETranslations } from '@onekeyhq/shared/src/locale'; +import { EOnboardingPages } from '@onekeyhq/shared/src/routes'; + +import { useBuyOneKeyHeaderRightButton } from '../../hooks/useBuyOneKeyHeaderRightButton'; + +function DeviceGuideModal() { + const intl = useIntl(); + const navigation = useAppNavigation(); + const { headerRight } = useBuyOneKeyHeaderRightButton(); + + const handleStartConnect = useCallback(() => { + navigation.push(EOnboardingPages.ConnectYourDevice); + }, [navigation]); + + return ( + + + + + OneKey devices + + + + + {intl.formatMessage({ + id: ETranslations.global_no_device_connected, + })} + + + {intl.formatMessage({ + id: ETranslations.global_no_device_connected_desc, + })} + + + + + + + + ); +} + +export default DeviceGuideModal; diff --git a/packages/kit/src/views/DeviceManagement/pages/DeviceManagementListModal/index.tsx b/packages/kit/src/views/DeviceManagement/pages/DeviceManagementListModal/index.tsx new file mode 100644 index 00000000000..fdea3ae5d53 --- /dev/null +++ b/packages/kit/src/views/DeviceManagement/pages/DeviceManagementListModal/index.tsx @@ -0,0 +1,175 @@ +import { useCallback, useEffect, useMemo } from 'react'; + +import { useIntl } from 'react-intl'; + +import { + Anchor, + Icon, + ListView, + Page, + SizableText, + XStack, +} from '@onekeyhq/components'; +import backgroundApiProxy from '@onekeyhq/kit/src/background/instance/backgroundApiProxy'; +import { ListItem } from '@onekeyhq/kit/src/components/ListItem'; +import type { IWalletAvatarProps } from '@onekeyhq/kit/src/components/WalletAvatar'; +import { WalletAvatar } from '@onekeyhq/kit/src/components/WalletAvatar'; +import useAppNavigation from '@onekeyhq/kit/src/hooks/useAppNavigation'; +import { usePromiseResult } from '@onekeyhq/kit/src/hooks/usePromiseResult'; +import { + EAppEventBusNames, + appEventBus, +} from '@onekeyhq/shared/src/eventBus/appEventBus'; +import { ETranslations } from '@onekeyhq/shared/src/locale'; +import { + EModalDeviceManagementRoutes, + EModalRoutes, + EOnboardingPages, +} from '@onekeyhq/shared/src/routes'; +import accountUtils from '@onekeyhq/shared/src/utils/accountUtils'; +import type { IHwQrWalletWithDevice } from '@onekeyhq/shared/types/account'; + +import { useBuyOneKeyHeaderRightButton } from '../../hooks/useBuyOneKeyHeaderRightButton'; + +function DeviceManagementListModal() { + const intl = useIntl(); + const appNavigation = useAppNavigation(); + const { result: hwQrWalletList = [], run: refreshHwQrWalletList } = + usePromiseResult>(async () => { + const r = + await backgroundApiProxy.serviceAccount.getAllHwQrWalletWithDevice(); + return Object.values(r).filter((item): item is IHwQrWalletWithDevice => + Boolean(item.device), + ); + }, []); + + useEffect(() => { + const fn = () => { + void refreshHwQrWalletList(); + }; + appEventBus.on(EAppEventBusNames.WalletUpdate, fn); + return () => { + appEventBus.off(EAppEventBusNames.WalletUpdate, fn); + }; + }, [refreshHwQrWalletList]); + + const onAddDevice = useCallback(async () => { + appNavigation.pushModal(EModalRoutes.OnboardingModal, { + screen: EOnboardingPages.ConnectYourDevice, + }); + }, [appNavigation]); + + const onWalletPressed = useCallback( + (wallet: IHwQrWalletWithDevice['wallet']) => { + if (wallet.id) { + appNavigation.push(EModalDeviceManagementRoutes.DeviceDetailModal, { + walletId: wallet.id, + }); + } + }, + [appNavigation], + ); + + const renderItem = useCallback( + ({ item }: { item: IHwQrWalletWithDevice }) => { + const walletAvatarProps: IWalletAvatarProps = { + wallet: item.wallet, + status: 'default', + badge: accountUtils.isQrWallet({ walletId: item.wallet.id }) + ? 'QR' + : undefined, + }; + return ( + } + onPress={() => { + onWalletPressed(item.wallet); + }} + /> + ); + }, + [onWalletPressed], + ); + + const footer = useMemo( + () => ( + ( + + + + )} + title={intl.formatMessage({ + id: ETranslations.global_add_new_device, + })} + drillIn + onPress={onAddDevice} + /> + ), + [intl, onAddDevice], + ); + + const { headerRight } = useBuyOneKeyHeaderRightButton({ + inDeviceManagementStack: true, + }); + + return ( + + + + item.wallet.id} + data={hwQrWalletList} + renderItem={renderItem} + estimatedItemSize={68} + ListFooterComponent={footer} + /> + + + {intl.formatMessage({ + id: ETranslations.global_onekey_prompt_dont_have_yet, + })} + + + {intl.formatMessage({ id: ETranslations.global_buy_one })} + + + + + ); +} + +export default DeviceManagementListModal; diff --git a/packages/kit/src/views/DeviceManagement/router/index.tsx b/packages/kit/src/views/DeviceManagement/router/index.tsx new file mode 100644 index 00000000000..db04c79b37c --- /dev/null +++ b/packages/kit/src/views/DeviceManagement/router/index.tsx @@ -0,0 +1,45 @@ +import type { IModalFlowNavigatorConfig } from '@onekeyhq/components'; +import { LazyLoadPage } from '@onekeyhq/kit/src/components/LazyLoadPage'; +import type { IModalDeviceManagementParamList } from '@onekeyhq/shared/src/routes'; +import { EModalDeviceManagementRoutes } from '@onekeyhq/shared/src/routes/deviceManagement'; + +const DeviceGuideModal = LazyLoadPage( + () => import('../pages/DeviceGuideModal'), +); + +const DeviceListModal = LazyLoadPage( + () => import('../pages/DeviceManagementListModal'), +); + +const DeviceDetailModal = LazyLoadPage( + () => import('../pages/DeviceDetailsModal'), +); + +const BuyOneKeyHardwareWallet = LazyLoadPage( + () => + import( + '@onekeyhq/kit/src/views/Onboarding/pages/ConnectHardwareWallet/OneKeyHardwareWallet' + ), +); + +export const DeviceManagementStacks: IModalFlowNavigatorConfig< + EModalDeviceManagementRoutes, + IModalDeviceManagementParamList +>[] = [ + { + name: EModalDeviceManagementRoutes.GuideModal, + component: DeviceGuideModal, + }, + { + name: EModalDeviceManagementRoutes.DeviceListModal, + component: DeviceListModal, + }, + { + name: EModalDeviceManagementRoutes.DeviceDetailModal, + component: DeviceDetailModal, + }, + { + name: EModalDeviceManagementRoutes.BuyOneKeyHardwareWallet, + component: BuyOneKeyHardwareWallet, + }, +]; diff --git a/packages/kit/src/views/Discovery/components/HeaderLeftToolBar/index.tsx b/packages/kit/src/views/Discovery/components/HeaderLeftToolBar/index.tsx index 403d7eb2d5f..9814b33c12b 100644 --- a/packages/kit/src/views/Discovery/components/HeaderLeftToolBar/index.tsx +++ b/packages/kit/src/views/Discovery/components/HeaderLeftToolBar/index.tsx @@ -131,9 +131,9 @@ function HeaderLeftToolBar({ testID={`action-header-item-${loading ? 'stop-loading' : 'reload'}`} /> - + {orderTabs.map((t) => ( diff --git a/packages/kit/src/views/Onboarding/pages/ConnectHardwareWallet/ConnectYourDevice.tsx b/packages/kit/src/views/Onboarding/pages/ConnectHardwareWallet/ConnectYourDevice.tsx index 9661c01fc4e..f67d2cf7445 100644 --- a/packages/kit/src/views/Onboarding/pages/ConnectHardwareWallet/ConnectYourDevice.tsx +++ b/packages/kit/src/views/Onboarding/pages/ConnectHardwareWallet/ConnectYourDevice.tsx @@ -86,6 +86,7 @@ import { type IOneKeyDeviceFeatures, } from '@onekeyhq/shared/types/device'; +import { useBuyOneKeyHeaderRightButton } from '../../../DeviceManagement/hooks/useBuyOneKeyHeaderRightButton'; import { useFirmwareUpdateActions } from '../../../FirmwareUpdate/hooks/useFirmwareUpdateActions'; import { useFirmwareVerifyDialog } from './FirmwareVerifyDialog'; @@ -102,10 +103,6 @@ type IConnectYourDeviceItem = { device: SearchDevice | undefined; }; -const headerRight = (onPress: () => void) => ( - -); - function DeviceListItem({ item }: { item: IConnectYourDeviceItem }) { const [isLoading, setIsLoading] = useState(false); return ( @@ -1185,9 +1182,8 @@ export function ConnectYourDevicePage() { channel ?? EConnectDeviceChannel.usbOrBle, ); - const toOneKeyHardwareWalletPage = useCallback(() => { - navigation.push(EOnboardingPages.OneKeyHardwareWallet); - }, [navigation]); + const { headerRight, toOneKeyHardwareWalletPage } = + useBuyOneKeyHeaderRightButton(); return ( @@ -1195,7 +1191,7 @@ export function ConnectYourDevicePage() { title={intl.formatMessage({ id: ETranslations.onboarding_connect_your_device, })} - headerRight={() => headerRight(toOneKeyHardwareWalletPage)} + headerRight={headerRight} /> diff --git a/packages/kit/src/views/Onboarding/router/index.ts b/packages/kit/src/views/Onboarding/router/index.ts index 5cce64c197c..05eb4fa7e26 100644 --- a/packages/kit/src/views/Onboarding/router/index.ts +++ b/packages/kit/src/views/Onboarding/router/index.ts @@ -76,6 +76,10 @@ const ImportKeyTag = LazyLoadPage( () => import('../pages/ImportWallet/ImportKeyTag'), ); +const DeviceManagementGuideModal = LazyLoadPage( + () => import('../../DeviceManagement/pages/DeviceGuideModal'), +); + export const OnboardingRouter: IModalFlowNavigatorConfig< EOnboardingPages, IOnboardingParamList @@ -178,4 +182,10 @@ export const OnboardingRouter: IModalFlowNavigatorConfig< component: FinalizeWalletSetup, allowDisableClose: true, }, + + // device management guide page + { + name: EOnboardingPages.DeviceManagementGuide, + component: DeviceManagementGuideModal, + }, ]; diff --git a/packages/kit/src/views/Setting/pages/List/DefaultSection/index.tsx b/packages/kit/src/views/Setting/pages/List/DefaultSection/index.tsx index 42d65b3f8ce..2a7154945cc 100644 --- a/packages/kit/src/views/Setting/pages/List/DefaultSection/index.tsx +++ b/packages/kit/src/views/Setting/pages/List/DefaultSection/index.tsx @@ -4,15 +4,12 @@ import { useIntl } from 'react-intl'; import { YStack } from '@onekeyhq/components'; import backgroundApiProxy from '@onekeyhq/kit/src/background/instance/backgroundApiProxy'; -import { showAddressSafeNotificationDialog } from '@onekeyhq/kit/src/components/AddressInput/AddressSafeDialog'; import { ListItem } from '@onekeyhq/kit/src/components/ListItem'; import useAppNavigation from '@onekeyhq/kit/src/hooks/useAppNavigation'; import { usePromiseResult } from '@onekeyhq/kit/src/hooks/usePromiseResult'; +import { useShowAddressBook } from '@onekeyhq/kit/src/hooks/useShowAddressBook'; import { useBackupEntryStatus } from '@onekeyhq/kit/src/views/CloudBackup/components/useBackupEntryStatus'; -import { - useAddressBookPersistAtom, - usePasswordPersistAtom, -} from '@onekeyhq/kit-bg/src/states/jotai/atoms'; +import { usePasswordPersistAtom } from '@onekeyhq/kit-bg/src/states/jotai/atoms'; import { EAppEventBusNames, appEventBus, @@ -24,7 +21,6 @@ import { ECloudBackupRoutes, EDAppConnectionModal, ELiteCardRoutes, - EModalAddressBookRoutes, EModalKeyTagRoutes, EModalRoutes, } from '@onekeyhq/shared/src/routes'; @@ -47,22 +43,9 @@ export const useOnLock = () => { const AddressBookItem = () => { const intl = useIntl(); - const navigation = useAppNavigation(); - const showAddressBook = useCallback(async () => { - await backgroundApiProxy.servicePassword.promptPasswordVerify(); - navigation.push(EModalAddressBookRoutes.ListItemModal); - defaultLogger.setting.page.enterAddressBook(); - }, [navigation]); - const [{ hideDialogInfo }] = useAddressBookPersistAtom(); - const onPress = useCallback(async () => { - if (!hideDialogInfo) { - await showAddressSafeNotificationDialog({ - intl, - }); - await backgroundApiProxy.serviceAddressBook.hideDialogInfo(); - } - await showAddressBook(); - }, [hideDialogInfo, showAddressBook, intl]); + const onPress = useShowAddressBook({ + useNewModal: false, + }); return ( { - if (features.label) { + if (features.label && !buildModelName) { return features.label; } const defaultLabelsByDeviceType: Record = { diff --git a/packages/shared/types/account.ts b/packages/shared/types/account.ts index 2fa050bae84..e4f66650dea 100644 --- a/packages/shared/types/account.ts +++ b/packages/shared/types/account.ts @@ -1,4 +1,8 @@ -import type { IDBAccount } from '@onekeyhq/kit-bg/src/dbs/local/types'; +import type { + IDBAccount, + IDBDevice, + IDBWallet, +} from '@onekeyhq/kit-bg/src/dbs/local/types'; import type { IAirGapAccount } from '@onekeyhq/qr-wallet-sdk'; import type { INetworkAccountAddressDetail } from './address'; @@ -42,3 +46,8 @@ export enum ERequestWalletTypeEnum { THIRD_PARTY = 'third-party', UNKNOWN = 'unknown', } + +export type IHwQrWalletWithDevice = { + device: IDBDevice | undefined; + wallet: IDBWallet; +}; diff --git a/yarn.lock b/yarn.lock index e5e9534ffc3..f0e91a82fe3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6224,23 +6224,23 @@ __metadata: languageName: node linkType: hard -"@onekeyfe/hd-ble-sdk@npm:1.0.20-alpha.1": - version: 1.0.20-alpha.1 - resolution: "@onekeyfe/hd-ble-sdk@npm:1.0.20-alpha.1" +"@onekeyfe/hd-ble-sdk@npm:^1.0.20-alpha.2": + version: 1.0.20-alpha.2 + resolution: "@onekeyfe/hd-ble-sdk@npm:1.0.20-alpha.2" dependencies: - "@onekeyfe/hd-core": "npm:^1.0.20-alpha.1" - "@onekeyfe/hd-shared": "npm:^1.0.20-alpha.1" - "@onekeyfe/hd-transport-react-native": "npm:^1.0.20-alpha.1" - checksum: 10/fe0f3ebefdf462437f6c5edaf4aef247e431d01ec3d4d039b8b4d6dbb6c9768a65d6f6a8b7f18496b8ec12f1cabc29b9c20b1f4919525fcc82f8f888da65298e + "@onekeyfe/hd-core": "npm:^1.0.20-alpha.2" + "@onekeyfe/hd-shared": "npm:^1.0.20-alpha.2" + "@onekeyfe/hd-transport-react-native": "npm:^1.0.20-alpha.2" + checksum: 10/140e2f4d8696e3ef8dbf5965f7e86ed6f0eede9d230d61f6704c06dc1d5819726eb47714013e26bc9b2e95a4c3445599de653250451c9ac5e6029fba9da3e0a9 languageName: node linkType: hard -"@onekeyfe/hd-core@npm:1.0.20-alpha.1, @onekeyfe/hd-core@npm:^1.0.20-alpha.1": - version: 1.0.20-alpha.1 - resolution: "@onekeyfe/hd-core@npm:1.0.20-alpha.1" +"@onekeyfe/hd-core@npm:^1.0.20-alpha.2": + version: 1.0.20-alpha.2 + resolution: "@onekeyfe/hd-core@npm:1.0.20-alpha.2" dependencies: - "@onekeyfe/hd-shared": "npm:^1.0.20-alpha.1" - "@onekeyfe/hd-transport": "npm:^1.0.20-alpha.1" + "@onekeyfe/hd-shared": "npm:^1.0.20-alpha.2" + "@onekeyfe/hd-transport": "npm:^1.0.20-alpha.2" axios: "npm:^0.27.2" bignumber.js: "npm:^9.0.2" bytebuffer: "npm:^5.0.1" @@ -6250,71 +6250,71 @@ __metadata: peerDependencies: "@noble/hashes": ^1.1.3 ripple-keypairs: ^1.1.4 - checksum: 10/52b6b5840eb76e43ba7fc83f422920698683a3bcc3145f23207402f9cec5fbef1f5ace873e76410a35b13fb236190f7872df6f53fe9024175c0ab25eae8f10cd + checksum: 10/6a5d8e6645cf23e692e9c4abb4034d2c123c08ac96581196b0dea65bfcf6445a3fe450d910c0b0f733be569e214aa4ebfed855b0e89052fa5902b5a4943c932e languageName: node linkType: hard -"@onekeyfe/hd-shared@npm:1.0.20-alpha.1, @onekeyfe/hd-shared@npm:^1.0.20-alpha.1": - version: 1.0.20-alpha.1 - resolution: "@onekeyfe/hd-shared@npm:1.0.20-alpha.1" - checksum: 10/e30e22d5922e537cdc251889640c8022c2a244f7d05f1476037998436f5b40640557622a47abc2e63b578f976ee37d33d501632372597a3fd21c0a1dedfeca76 +"@onekeyfe/hd-shared@npm:^1.0.20-alpha.2": + version: 1.0.20-alpha.2 + resolution: "@onekeyfe/hd-shared@npm:1.0.20-alpha.2" + checksum: 10/b090c2c818a0599f474afd4b603b840fa3ed8574ceb00c47a03f817be2b81d5fc6dc5bbaf2be5d3b45c9522fc1af601460ac0c0dc6a3d32ead5a56defd20db83 languageName: node linkType: hard -"@onekeyfe/hd-transport-http@npm:^1.0.20-alpha.1": - version: 1.0.20-alpha.1 - resolution: "@onekeyfe/hd-transport-http@npm:1.0.20-alpha.1" +"@onekeyfe/hd-transport-http@npm:^1.0.20-alpha.2": + version: 1.0.20-alpha.2 + resolution: "@onekeyfe/hd-transport-http@npm:1.0.20-alpha.2" dependencies: - "@onekeyfe/hd-shared": "npm:^1.0.20-alpha.1" - "@onekeyfe/hd-transport": "npm:^1.0.20-alpha.1" + "@onekeyfe/hd-shared": "npm:^1.0.20-alpha.2" + "@onekeyfe/hd-transport": "npm:^1.0.20-alpha.2" axios: "npm:^0.27.2" - checksum: 10/9653d2e3a6e08b38faf1c6b08939f0283828628cd5df9704d2cce401a164b66e7990fd3f4e283e2d1b2668bfa8d1c9ddd533f77598d456f27aa5b6cfba2b84cb + checksum: 10/dd1505ffcffd8137f033e9a8fe09b38ac93378577faa8acc372e185161950ded40d0b2e05dd020edb2a087037482f1c80bcb4c08d3d4d910a201f127eef519d6 languageName: node linkType: hard -"@onekeyfe/hd-transport-react-native@npm:^1.0.20-alpha.1": - version: 1.0.20-alpha.1 - resolution: "@onekeyfe/hd-transport-react-native@npm:1.0.20-alpha.1" +"@onekeyfe/hd-transport-react-native@npm:^1.0.20-alpha.2": + version: 1.0.20-alpha.2 + resolution: "@onekeyfe/hd-transport-react-native@npm:1.0.20-alpha.2" dependencies: - "@onekeyfe/hd-shared": "npm:^1.0.20-alpha.1" - "@onekeyfe/hd-transport": "npm:^1.0.20-alpha.1" + "@onekeyfe/hd-shared": "npm:^1.0.20-alpha.2" + "@onekeyfe/hd-transport": "npm:^1.0.20-alpha.2" "@onekeyfe/react-native-ble-plx": "npm:3.0.1" react-native-ble-manager: "npm:^8.1.0" - checksum: 10/728548167de60c74207add075e7cf8d54fdf9a1425005a183417cc7464a89c1f607a1f05a0e32795c8c3b30d1f06d45d22192bd6081f1181ebbe89b0519313a7 + checksum: 10/99a6d41732ca50e02794ee1250c5a70645549929cbe7618c4377d15c17dc610dd22ef5743b8dfbb60811ead2e3a3f14fd28fa841d8535f42a181f4a74452cf8e languageName: node linkType: hard -"@onekeyfe/hd-transport-webusb@npm:^1.0.20-alpha.1": - version: 1.0.20-alpha.1 - resolution: "@onekeyfe/hd-transport-webusb@npm:1.0.20-alpha.1" +"@onekeyfe/hd-transport-webusb@npm:^1.0.20-alpha.2": + version: 1.0.20-alpha.2 + resolution: "@onekeyfe/hd-transport-webusb@npm:1.0.20-alpha.2" dependencies: - "@onekeyfe/hd-shared": "npm:^1.0.20-alpha.1" - "@onekeyfe/hd-transport": "npm:^1.0.20-alpha.1" - checksum: 10/cbecd661b271272f59cae613e4b1b24ac35ff0ed7e7cb7489fdb3226faedd6616820b85a0e01a84d771d008992c0419b8b232eb63b5548ba56bb08e1632e8c49 + "@onekeyfe/hd-shared": "npm:^1.0.20-alpha.2" + "@onekeyfe/hd-transport": "npm:^1.0.20-alpha.2" + checksum: 10/c1926888e904012e7092df6e2ad49430811f1315e513a9a820ab8350366a95498db5df81c9600c1d008f0931500399180498c4fe1a7a332d77692f5881389ce4 languageName: node linkType: hard -"@onekeyfe/hd-transport@npm:1.0.20-alpha.1, @onekeyfe/hd-transport@npm:^1.0.20-alpha.1": - version: 1.0.20-alpha.1 - resolution: "@onekeyfe/hd-transport@npm:1.0.20-alpha.1" +"@onekeyfe/hd-transport@npm:^1.0.20-alpha.2": + version: 1.0.20-alpha.2 + resolution: "@onekeyfe/hd-transport@npm:1.0.20-alpha.2" dependencies: bytebuffer: "npm:^5.0.1" long: "npm:^4.0.0" protobufjs: "npm:^6.11.2" - checksum: 10/831a39de387f16d2f9a5cbdf3b8dfe865634fb53ccb3becbd90fdb9e480f7dfb68abe405563b583ee957612658615f57aaf600e74eb8f257caa9168472ff6c6b + checksum: 10/34126c59aae9674aedc7335ddfc103918fb8c26a402e9c7516493f0e8d2f3b3ede41c91fe9fd151ec79f8a529838582036be15f75f39daa02420deb47cd7d4dc languageName: node linkType: hard -"@onekeyfe/hd-web-sdk@npm:1.0.20-alpha.1": - version: 1.0.20-alpha.1 - resolution: "@onekeyfe/hd-web-sdk@npm:1.0.20-alpha.1" +"@onekeyfe/hd-web-sdk@npm:^1.0.20-alpha.2": + version: 1.0.20-alpha.2 + resolution: "@onekeyfe/hd-web-sdk@npm:1.0.20-alpha.2" dependencies: "@onekeyfe/cross-inpage-provider-core": "npm:^0.0.17" - "@onekeyfe/hd-core": "npm:^1.0.20-alpha.1" - "@onekeyfe/hd-shared": "npm:^1.0.20-alpha.1" - "@onekeyfe/hd-transport-http": "npm:^1.0.20-alpha.1" - "@onekeyfe/hd-transport-webusb": "npm:^1.0.20-alpha.1" - checksum: 10/679fdc7364a8265f5fbef444b92926edb1ea7192fb0269c4220feef19fa855248f9c5c66812587b1bdfd81a525213059cf6a5ab986012e1a80194533a22634fd + "@onekeyfe/hd-core": "npm:^1.0.20-alpha.2" + "@onekeyfe/hd-shared": "npm:^1.0.20-alpha.2" + "@onekeyfe/hd-transport-http": "npm:^1.0.20-alpha.2" + "@onekeyfe/hd-transport-webusb": "npm:^1.0.20-alpha.2" + checksum: 10/bbd5a9df8e4b0157b6dec7ae8b163b52788b1f006acdb1d915beb208f1ccad7788e031b403884fe1e99a1630df97b27facb43d6a69557c666a24ad8ccd3b7bb3 languageName: node linkType: hard @@ -6728,11 +6728,11 @@ __metadata: "@onekeyfe/cross-inpage-provider-injected": "npm:2.2.10" "@onekeyfe/cross-inpage-provider-types": "npm:2.2.10" "@onekeyfe/extension-bridge-hosted": "npm:2.2.10" - "@onekeyfe/hd-ble-sdk": "npm:1.0.20-alpha.1" - "@onekeyfe/hd-core": "npm:1.0.20-alpha.1" - "@onekeyfe/hd-shared": "npm:1.0.20-alpha.1" - "@onekeyfe/hd-transport": "npm:1.0.20-alpha.1" - "@onekeyfe/hd-web-sdk": "npm:1.0.20-alpha.1" + "@onekeyfe/hd-ble-sdk": "npm:^1.0.20-alpha.2" + "@onekeyfe/hd-core": "npm:^1.0.20-alpha.2" + "@onekeyfe/hd-shared": "npm:^1.0.20-alpha.2" + "@onekeyfe/hd-transport": "npm:^1.0.20-alpha.2" + "@onekeyfe/hd-web-sdk": "npm:^1.0.20-alpha.2" "@onekeyfe/onekey-cross-webview": "npm:2.2.10" "@open-wc/webpack-import-meta-loader": "npm:^0.4.7" "@pmmmwh/react-refresh-webpack-plugin": "npm:^0.5.11" @@ -6998,7 +6998,7 @@ __metadata: cross-env: "npm:^7.0.3" electron: "npm:27.3.1" electron-builder: "npm:24.13.3" - electron-check-biometric-auth-changed: "npm:0.0.4" + electron-check-biometric-auth-changed: "npm:0.0.6" electron-context-menu: "npm:^3.5.0" electron-is-dev: "npm:^2.0.0" electron-log: "npm:5.2.0" @@ -22028,14 +22028,14 @@ __metadata: languageName: node linkType: hard -"electron-check-biometric-auth-changed@npm:0.0.4": - version: 0.0.4 - resolution: "electron-check-biometric-auth-changed@npm:0.0.4" +"electron-check-biometric-auth-changed@npm:0.0.6": + version: 0.0.6 + resolution: "electron-check-biometric-auth-changed@npm:0.0.6" dependencies: bindings: "npm:^1.5.0" node-addon-api: "npm:^7.1.0" node-gyp: "npm:latest" - checksum: 10/c42556e77eb000d6fae2085ceaaa325f5c69d95c96ee7adca311f1cd111f816878cc0ac4b7adae8786c5aaaedd2726dcdf41f467f896eb046a68e3475afcd6c7 + checksum: 10/daf0bc6d4cddf7c411d4c315910854c974fbc62c9ea7a12bf23bc368c452f0e0bcff5f4b127de9f4145b62c020e2a02d592b781de730926355ef9e1138af6142 languageName: node linkType: hard