From 8298d003f63df31d00f082ada1b55b03b3c91dbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20V=C3=A1clav=C3=ADk?= Date: Tue, 11 Feb 2025 14:50:44 +0100 Subject: [PATCH] WIP --- .../suite/layouts/SuiteLayout/SuiteLayout.tsx | 91 ++++++++++--------- .../DeviceContextModal/DeviceContextModal.tsx | 1 + .../DeviceContextModal/PassphraseModal.tsx | 4 +- .../PassphraseModalContext.tsx | 57 ++++++++++++ .../PassphraseWalletBestPractices.tsx | 28 ++++++ .../PassphraseWalletConfirmation.tsx | 8 +- .../PassphraseWalletConfirmationStep2.tsx | 16 +--- .../ReduxModal/DeviceContextModal/types.ts | 2 +- .../DeviceItem/AddWalletButton.tsx | 72 +++++++++++---- .../views/suite/SwitchDevice/SwitchDevice.tsx | 29 +++++- 10 files changed, 231 insertions(+), 77 deletions(-) create mode 100644 packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/PassphraseModalContext.tsx create mode 100644 packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/PassphraseWalletBestPractices.tsx diff --git a/packages/suite/src/components/suite/layouts/SuiteLayout/SuiteLayout.tsx b/packages/suite/src/components/suite/layouts/SuiteLayout/SuiteLayout.tsx index a689ee28658..a42f0ddf45f 100644 --- a/packages/suite/src/components/suite/layouts/SuiteLayout/SuiteLayout.tsx +++ b/packages/suite/src/components/suite/layouts/SuiteLayout/SuiteLayout.tsx @@ -33,6 +33,7 @@ import { MobileMenu } from './MobileMenu/MobileMenu'; import { Sidebar } from './Sidebar/Sidebar'; import { useAppShortcuts } from './useAppShortcuts'; import { ModalSwitcher } from '../../modals/ModalSwitcher/ModalSwitcher'; +import { PassphraseModalProvider } from '../../modals/ReduxModal/DeviceContextModal/PassphraseModalContext'; export const SCROLL_WRAPPER_ID = 'layout-scroll'; export const Wrapper = styled.div` @@ -162,49 +163,53 @@ export const SuiteLayout = ({ children }: SuiteLayoutProps) => { - - - - - - {isMobileLayout && } - - {isMobileLayout && } - - - - - - - {!isMobileLayout && ( - - - - )} - - {!isMobileLayout && } - - - - {isMobileLayout && isAccountPage && ( - - )} - {layoutHeader} - - {children} - - - - - - - - {!isMobileLayout && } - + + + + + + + {isMobileLayout && } + + {isMobileLayout && } + + + + + + + {!isMobileLayout && ( + + + + )} + + {!isMobileLayout && } + + + + {isMobileLayout && isAccountPage && ( + + )} + {layoutHeader} + + + {children} + + + + + + + + + {!isMobileLayout && } + + diff --git a/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/DeviceContextModal.tsx b/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/DeviceContextModal.tsx index 8e678636a26..13a5f7e76c2 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/DeviceContextModal.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/DeviceContextModal.tsx @@ -21,6 +21,7 @@ import { useSelector } from 'src/hooks/suite'; import messages from 'src/support/messages'; import type { ReduxModalProps } from '../ReduxModal'; +import { PassphraseModalProvider } from './PassphraseModalContext'; /** Modals requested by Device from `trezor-connect` */ export const DeviceContextModal = ({ diff --git a/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/PassphraseModal.tsx b/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/PassphraseModal.tsx index e547385a214..59308eeba2c 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/PassphraseModal.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/PassphraseModal.tsx @@ -1,4 +1,4 @@ -import { useCallback } from 'react'; +import { useCallback, useEffect } from 'react'; import { onPassphraseSubmit, @@ -19,6 +19,8 @@ import type { TrezorDevice } from 'src/types/suite'; import { CardWithDevice } from 'src/views/suite/SwitchDevice/CardWithDevice'; import { SwitchDeviceModal } from 'src/views/suite/SwitchDevice/SwitchDeviceModal'; +import { usePassphraseModalContext } from './PassphraseModalContext'; +import { PassphraseWalletBestPractices } from './PassphraseWalletBestPractices'; import { PassphraseWalletConfirmation } from './PassphraseWalletConfirmation'; interface PassphraseModalProps { diff --git a/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/PassphraseModalContext.tsx b/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/PassphraseModalContext.tsx new file mode 100644 index 00000000000..68d3a7b4524 --- /dev/null +++ b/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/PassphraseModalContext.tsx @@ -0,0 +1,57 @@ +import React, { createContext, useContext, useState } from 'react'; + +import type { TrezorDevice } from '@suite-common/suite-types/libDev/src'; + +type PassphraseState = 'initial' | 'best-practices'; + +const INITIAL_STATE: PassphraseState = 'initial'; + +type PassphraseModalContextType = { + passphraseState: PassphraseState; + setPassphraseState: (passphraseState: PassphraseState) => void; + device: TrezorDevice | undefined; + setDevice: (device: TrezorDevice) => void; +}; + +type PassphraseModalProviderProps = { + children: React.ReactNode; +}; + +const initialPassphraseModal: PassphraseModalContextType = { + passphraseState: INITIAL_STATE, + setPassphraseState: () => {}, + device: undefined, + setDevice: () => {}, +}; + +export const PassphraseModalContext = + createContext(initialPassphraseModal); + +export const PassphraseModalProvider = ({ children }: PassphraseModalProviderProps) => { + const [passphraseState, setPassphraseState] = useState( + initialPassphraseModal.passphraseState, + ); + const [device, setDevice] = useState(undefined); + + const value: PassphraseModalContextType = { + passphraseState, + setPassphraseState, + device, + setDevice, + }; + + return ( + {children} + ); +}; + +PassphraseModalProvider.displayName = 'PassphraseModalProvider'; + +export const usePassphraseModalContext = () => { + const context = useContext(PassphraseModalContext); + if (!context) { + throw new Error('usePassphraseModalContext must be used within a PassphraseModalProvider'); + } + + return context; +}; diff --git a/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/PassphraseWalletBestPractices.tsx b/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/PassphraseWalletBestPractices.tsx new file mode 100644 index 00000000000..4ad2486aa60 --- /dev/null +++ b/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/PassphraseWalletBestPractices.tsx @@ -0,0 +1,28 @@ +import { PassphraseWalletConfirmationStep2 } from './PassphraseWalletConfirmationStep2'; +import { CardWithDevice } from '../../../../../views/suite/SwitchDevice/CardWithDevice'; +import { SwitchDeviceModal } from '../../../../../views/suite/SwitchDevice/SwitchDeviceModal'; + +type PassphraseWalletBestPracticesProps = { + onCancel: () => void; + onNext: () => void; + onBack: () => void; + device: any; +}; + +export const PassphraseWalletBestPractices = ({ + onCancel, + onNext, + onBack, + device, +}: PassphraseWalletBestPracticesProps) => ( + + + + + + ); diff --git a/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/PassphraseWalletConfirmation.tsx b/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/PassphraseWalletConfirmation.tsx index e4761045849..684b4241769 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/PassphraseWalletConfirmation.tsx +++ b/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/PassphraseWalletConfirmation.tsx @@ -37,7 +37,13 @@ const PassphraseWalletConfirmationContent = ({ /> ); case 'step2': - return ; + return ( + { + setContentType('step3'); + }} + /> + ); case 'step3': return ( >; + onNext: () => void; }; export const PassphraseWalletConfirmationStep2 = ({ - setContentType, + onNext, }: PassphraseWalletConfirmationStep2Props) => (

@@ -37,13 +33,7 @@ export const PassphraseWalletConfirmationStep2 = ({ - diff --git a/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/types.ts b/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/types.ts index 005aaf7ad5d..7daa5eb291e 100644 --- a/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/types.ts +++ b/packages/suite/src/components/suite/modals/ReduxModal/DeviceContextModal/types.ts @@ -1 +1 @@ -export type ContentType = 'step1' | 'step2' | 'step3'; +// export type ContentType = 'step1' | 'step2' | 'step3'; diff --git a/packages/suite/src/views/suite/SwitchDevice/DeviceItem/AddWalletButton.tsx b/packages/suite/src/views/suite/SwitchDevice/DeviceItem/AddWalletButton.tsx index 6da9736e344..c311009072b 100644 --- a/packages/suite/src/views/suite/SwitchDevice/DeviceItem/AddWalletButton.tsx +++ b/packages/suite/src/views/suite/SwitchDevice/DeviceItem/AddWalletButton.tsx @@ -8,6 +8,9 @@ import { useDispatch, useSelector } from 'src/hooks/suite'; import { selectIsDeviceOrUiLocked } from 'src/reducers/suite/suiteReducer'; import { AcquiredDevice, ForegroundAppProps, TrezorDevice } from 'src/types/suite'; +import { usePassphraseModalContext } from '../../../../components/suite/modals/ReduxModal/DeviceContextModal/PassphraseModalContext'; +import { PassphraseWalletBestPractices } from '../../../../components/suite/modals/ReduxModal/DeviceContextModal/PassphraseWalletBestPractices'; + interface AddWalletButtonProps { device: TrezorDevice; instances: AcquiredDevice[]; @@ -26,9 +29,23 @@ export const AddWalletButton = ({ device, instances, onCancel }: AddWalletButton // and there is no point in useDevice returning the same device object we would have passed const isLocked = !device || !device.connected || isDeviceOrUiLocked; - const onAddWallet = ({ walletType }: { walletType: WalletType }) => { - dispatch(addWalletThunk({ walletType, device })); - onCancel(false); + const { setPassphraseState, passphraseState, setDevice } = usePassphraseModalContext(); + console.log('___!!!', passphraseState); + const onAddWallet = ({ + walletType, + isExisting, + }: { + walletType: WalletType; + isExisting: boolean; + }) => { + if (!isExisting) { + console.log('___isExisting', isExisting); + setPassphraseState('best-practices'); + setDevice(device); + } else { + dispatch(addWalletThunk({ walletType, device })); + onCancel(false); + } }; return ( @@ -45,26 +62,47 @@ export const AddWalletButton = ({ device, instances, onCancel }: AddWalletButton isFullWidth icon="plus" isDisabled={isLocked} - onClick={() => onAddWallet({ walletType: WalletType.STANDARD })} + onClick={() => + onAddWallet({ walletType: WalletType.STANDARD, isExisting: false }) + } > )} {isPassphraseProtectionEnabled && ( - + + + + )} diff --git a/packages/suite/src/views/suite/SwitchDevice/SwitchDevice.tsx b/packages/suite/src/views/suite/SwitchDevice/SwitchDevice.tsx index 59d9a9b5e3c..08fdd0c8d3f 100644 --- a/packages/suite/src/views/suite/SwitchDevice/SwitchDevice.tsx +++ b/packages/suite/src/views/suite/SwitchDevice/SwitchDevice.tsx @@ -1,18 +1,24 @@ import * as deviceUtils from '@suite-common/suite-utils'; import { selectDevices, selectSelectedDevice } from '@suite-common/wallet-core'; +import { WalletType } from '@suite-common/wallet-types'; import { Column } from '@trezor/components'; +import TrezorConnect from '@trezor/connect'; import { spacings } from '@trezor/theme'; -import { useSelector } from 'src/hooks/suite'; +import { useDispatch, useSelector } from 'src/hooks/suite'; import { ForegroundAppProps } from 'src/types/suite'; import { DeviceItem } from './DeviceItem/DeviceItem'; import { SwitchDeviceModal } from './SwitchDeviceModal'; +import { addWalletThunk } from '../../../actions/wallet/addWalletThunk'; +import { usePassphraseModalContext } from '../../../components/suite/modals/ReduxModal/DeviceContextModal/PassphraseModalContext'; +import { PassphraseWalletBestPractices } from '../../../components/suite/modals/ReduxModal/DeviceContextModal/PassphraseWalletBestPractices'; export const SwitchDevice = ({ onCancel }: ForegroundAppProps) => { const selectedDevice = useSelector(selectSelectedDevice); const devices = useSelector(selectDevices); + const dispatch = useDispatch(); // exclude selectedDevice from list, because other devices could have a higher priority // and we want to have selectedDevice on top const sortedDevices = deviceUtils @@ -24,6 +30,27 @@ export const SwitchDevice = ({ onCancel }: ForegroundAppProps) => { sortedDevices.unshift(selectedDevice); } + const { passphraseState, device, setPassphraseState } = usePassphraseModalContext(); + console.log('___ZMENA', passphraseState); + console.log('___//', passphraseState); + if (passphraseState === 'best-practices' && device) { + return ( + { + TrezorConnect.cancel('auth-confirm-cancel'); + }} + onNext={() => { + dispatch(addWalletThunk({ walletType: WalletType.PASSPHRASE, device })); + onCancel(false); + }} + onBack={() => { + setPassphraseState('initial'); + }} + device={device} + /> + ); + } + return (