Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: redesign welcome page #2593

Merged
merged 9 commits into from
Oct 6, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions public/images/common/check-filled.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions public/images/logo-text.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions public/images/welcome/logo-google.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 0 additions & 3 deletions src/components/common/ConnectWallet/AccountCenter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import ChainSwitcher from '../ChainSwitcher'
import useAddressBook from '@/hooks/useAddressBook'
import { type ConnectedWallet } from '@/hooks/wallets/useOnboard'
import WalletInfo, { UNKNOWN_CHAIN_NAME } from '../WalletInfo'
import { MPCWallet } from './MPCWallet'

const AccountCenter = ({ wallet }: { wallet: ConnectedWallet }) => {
const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null)
Expand Down Expand Up @@ -115,8 +114,6 @@ const AccountCenter = ({ wallet }: { wallet: ConnectedWallet }) => {
<Button onClick={handleDisconnect} variant="danger" size="small" fullWidth disableElevation>
Disconnect
</Button>

<MPCWallet />
</Paper>
</Popover>
</>
Expand Down
81 changes: 81 additions & 0 deletions src/components/common/ConnectWallet/MPCLogin.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { MPCWalletState } from '@/hooks/wallets/mpc/useMPCWallet'
import { Box, Button, SvgIcon, Typography } from '@mui/material'
import { useContext, useEffect, useState } from 'react'
import { MpcWalletContext } from './MPCWalletProvider'
import { PasswordRecovery } from './PasswordRecovery'
import GoogleLogo from '@/public/images/welcome/logo-google.svg'

import css from './styles.module.css'
import useWallet from '@/hooks/wallets/useWallet'

const MPCLogin = ({ onLogin }: { onLogin?: () => void }) => {
const { loginPending, triggerLogin, userInfo, walletState, recoverFactorWithPassword } = useContext(MpcWalletContext)

const wallet = useWallet()

const [loginTriggered, setLoginTriggered] = useState(false)

const login = async () => {
setLoginTriggered(true)
await triggerLogin()
}

// If login was triggered through the Button we immediately continue if logged in
useEffect(() => {
if (loginTriggered && wallet && onLogin) {
onLogin()
}
}, [loginTriggered, onLogin, wallet])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we call onLogin inside login?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so.
When triggerLogin resolves, it might result in a MANUAL_RECOVERY state, which will pop up the Password recovery modal.
So we have to react to a side effect here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here: Calling the callback after triggerLogin / recoverPassword resolves causes the useSyncSafeCreationStep to immediately redirect us back.


return (
<>
{wallet && userInfo.email ? (
<>
<Button
variant="outlined"
sx={{ padding: '8px 16px' }}
schmanu marked this conversation as resolved.
Show resolved Hide resolved
onClick={onLogin}
size="small"
disabled={loginPending}
fullWidth
>
<Box
width="100%"
justifyContent="space-between"
display="flex"
flexDirection="row"
alignItems="center"
gap={1}
>
<img
src={userInfo.profileImage}
className={css.profileImg}
alt="Profile Image"
referrerPolicy="no-referrer"
/>
<div className={css.profileData}>
<Typography variant="subtitle2" fontWeight={700}>
Continue as {userInfo.name}
</Typography>
<Typography variant="body2">{userInfo.email}</Typography>
</div>
<SvgIcon component={GoogleLogo} inheritViewBox fontSize="medium" />
</Box>
</Button>
</>
) : (
<Button variant="outlined" onClick={login} size="small" disabled={loginPending} fullWidth>
<Box display="flex" flexDirection="row" alignItems="center" gap={1}>
<SvgIcon component={GoogleLogo} inheritViewBox fontSize="medium" /> Continue with Google
</Box>
</Button>
)}

{walletState === MPCWalletState.MANUAL_RECOVERY && (
<PasswordRecovery recoverFactorWithPassword={recoverFactorWithPassword} />
)}
</>
)
}

export default MPCLogin
40 changes: 0 additions & 40 deletions src/components/common/ConnectWallet/MPCWallet.tsx

This file was deleted.

4 changes: 4 additions & 0 deletions src/components/common/ConnectWallet/MPCWalletProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ type MPCWalletContext = {
walletState: MPCWalletState
userInfo: {
email: string | undefined
profileImage: string | undefined
name: string | undefined
}
}

Expand All @@ -22,6 +24,8 @@ export const MpcWalletContext = createContext<MPCWalletContext>({
recoverFactorWithPassword: () => Promise.resolve(),
userInfo: {
email: undefined,
profileImage: undefined,
name: undefined,
},
schmanu marked this conversation as resolved.
Show resolved Hide resolved
})

Expand Down
4 changes: 2 additions & 2 deletions src/components/common/ConnectWallet/WalletDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { ReactElement } from 'react'

import KeyholeIcon from '@/components/common/icons/KeyholeIcon'
import useConnectWallet from '@/components/common/ConnectWallet/useConnectWallet'
import { MPCWallet } from './MPCWallet'
import MPCLogin from './MPCLogin'

const WalletDetails = ({ onConnect }: { onConnect?: () => void }): ReactElement => {
const connectWallet = useConnectWallet()
Expand All @@ -23,7 +23,7 @@ const WalletDetails = ({ onConnect }: { onConnect?: () => void }): ReactElement
Connect
</Button>

<MPCWallet />
<MPCLogin />
</>
)
}
Expand Down
107 changes: 107 additions & 0 deletions src/components/common/ConnectWallet/__tests__/MPCLogin.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import { act, render, waitFor } from '@/tests/test-utils'
import * as useWallet from '@/hooks/wallets/useWallet'
import * as useMPCWallet from '@/hooks/wallets/mpc/useMPCWallet'
import MPCLogin from '../MPCLogin'
import { hexZeroPad } from '@ethersproject/bytes'
import { type EIP1193Provider } from '@web3-onboard/common'
import { ONBOARD_MPC_MODULE_LABEL } from '@/services/mpc/module'
import { MpcWalletProvider } from '../MPCWalletProvider'

describe('MPCLogin', () => {
beforeEach(() => {
jest.resetAllMocks()
})

it('should render continue with connected account', async () => {
const mockOnLogin = jest.fn()
const walletAddress = hexZeroPad('0x1', 20)
jest.spyOn(useWallet, 'default').mockReturnValue({
address: walletAddress,
chainId: '5',
label: ONBOARD_MPC_MODULE_LABEL,
provider: {} as unknown as EIP1193Provider,
})
jest.spyOn(useMPCWallet, 'useMPCWallet').mockReturnValue({
userInfo: {
email: '[email protected]',
name: 'Test Testermann',
profileImage: 'test.png',
},
triggerLogin: jest.fn(),
walletState: useMPCWallet.MPCWalletState.READY,
} as unknown as useMPCWallet.MPCWalletHook)

const result = render(
<MpcWalletProvider>
<MPCLogin onLogin={mockOnLogin} />
</MpcWalletProvider>,
)

await waitFor(() => {
expect(result.findByText('Continue as Test Testermann')).resolves.toBeDefined()
})

// We do not automatically invoke the callback as the user did not actively connect
expect(mockOnLogin).not.toHaveBeenCalled()

const button = await result.findByRole('button')
button.click()

expect(mockOnLogin).toHaveBeenCalled()
})

it('should render google login button and invoke the callback on connection if no wallet is connected', async () => {
const mockOnLogin = jest.fn()
const walletAddress = hexZeroPad('0x1', 20)
const mockUseWallet = jest.spyOn(useWallet, 'default').mockReturnValue(null)
const mockTriggerLogin = jest.fn()
const mockUseMPCWallet = jest.spyOn(useMPCWallet, 'useMPCWallet').mockReturnValue({
userInfo: {
email: undefined,
name: undefined,
profileImage: undefined,
},
triggerLogin: mockTriggerLogin,
walletState: useMPCWallet.MPCWalletState.NOT_INITIALIZED,
} as unknown as useMPCWallet.MPCWalletHook)

const result = render(
<MpcWalletProvider>
<MPCLogin onLogin={mockOnLogin} />
</MpcWalletProvider>,
)

await waitFor(() => {
expect(result.findByText('Continue with Google')).resolves.toBeDefined()
})

// We do not automatically invoke the callback as the user did not actively connect
expect(mockOnLogin).not.toHaveBeenCalled()

await act(async () => {
// Click the button and mock a successful login
const button = await result.findByRole('button')
button.click()
mockUseMPCWallet.mockReset().mockReturnValue({
userInfo: {
email: '[email protected]',
name: 'Test Testermann',
profileImage: 'test.png',
},
triggerLogin: jest.fn(),
walletState: useMPCWallet.MPCWalletState.READY,
} as unknown as useMPCWallet.MPCWalletHook)

mockUseWallet.mockReset().mockReturnValue({
address: walletAddress,
chainId: '5',
label: ONBOARD_MPC_MODULE_LABEL,
provider: {} as unknown as EIP1193Provider,
})
})

await waitFor(() => {
expect(mockOnLogin).toHaveBeenCalled()
})
})
})
12 changes: 12 additions & 0 deletions src/components/common/ConnectWallet/styles.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,18 @@
width: 100%;
}

.profileImg {
border-radius: 16px;
schmanu marked this conversation as resolved.
Show resolved Hide resolved
width: 32px;
height: 32px;
}

.profileData {
display: flex;
flex-direction: column;
align-items: flex-start;
}

.rowContainer {
align-self: stretch;
margin-left: calc(var(--space-2) * -1);
Expand Down
Loading
Loading