Commit 80180014 authored by tom's avatar tom

custom behaviour of connect button on dapp page

parent 6e269424
......@@ -53,7 +53,7 @@ const HeroBanner = () => {
</Heading>
{ config.UI.navigation.layout === 'vertical' && (
<Box display={{ base: 'none', lg: 'block' }}>
{ config.features.account.isEnabled && <ProfileDesktop isHomePage/> }
{ config.features.account.isEnabled && <ProfileDesktop buttonVariant="hero"/> }
</Box>
) }
</Flex>
......
import { chakra, Flex, Tooltip, Skeleton } from '@chakra-ui/react';
import { chakra, Flex, Tooltip, Skeleton, Box } from '@chakra-ui/react';
import React from 'react';
import type { MarketplaceAppOverview, MarketplaceAppSecurityReport, ContractListTypes } from 'types/client/marketplace';
......@@ -97,9 +97,9 @@ const MarketplaceAppTopBar = ({ appId, data, isLoading, securityReport }: Props)
source="App page"
/>
{ !isMobile && (
<Flex flex="1" justifyContent="flex-end">
<Box ml="auto">
{ config.features.account.isEnabled && <ProfileDesktop buttonSize="sm"/> }
</Flex>
</Box>
) }
</Flex>
{ contractListType && (
......
import { Center, Spinner } from '@chakra-ui/react';
import { useWeb3Modal } from '@web3modal/wagmi/react';
import React from 'react';
import { useAccount, useSignMessage } from 'wagmi';
import type { Screen } from '../types';
import useApiFetch from 'lib/api/useApiFetch';
import getErrorMessage from 'lib/errors/getErrorMessage';
import useToast from 'lib/hooks/useToast';
import useSignInWithWallet from './useSignInWithWallet';
interface Props {
onSuccess: (screen: Screen) => void;
......@@ -15,46 +11,24 @@ interface Props {
}
const AuthModalScreenConnectWallet = ({ onSuccess, onError }: Props) => {
const isSigningRef = React.useRef(false);
const isStartedRef = React.useRef(false);
const apiFetch = useApiFetch();
const toast = useToast();
const web3Modal = useWeb3Modal();
const { isConnected, address } = useAccount();
const { signMessageAsync } = useSignMessage();
const handleSignInSuccess = React.useCallback(({ address }: { address: string }) => {
onSuccess({ type: 'success_created_wallet', address });
}, [ onSuccess ]);
React.useEffect(() => {
!isConnected && web3Modal.open();
}, [ isConnected, web3Modal ]);
const proceedToAuth = React.useCallback(async(address: string) => {
try {
const siweMessage = await apiFetch('auth_siwe_message', { queryParams: { address } }) as { siwe_message: string };
const signature = await signMessageAsync({ message: siweMessage.siwe_message });
await apiFetch('auth_siwe_verify', {
fetchParams: {
method: 'POST',
body: { message: siweMessage.siwe_message, signature },
},
});
onSuccess({ type: 'success_created_wallet', address });
} catch (error) {
// TODO @tom2drum show better error message
onError();
toast({
status: 'error',
title: 'Error',
description: getErrorMessage(error) || 'Something went wrong',
});
}
}, [ apiFetch, onError, onSuccess, signMessageAsync, toast ]);
const handleSignInError = React.useCallback(() => {
onError();
}, [ onError ]);
const { start } = useSignInWithWallet({ onSuccess: handleSignInSuccess, onError: handleSignInError });
React.useEffect(() => {
if (isConnected && address && !isSigningRef.current) {
isSigningRef.current = true;
proceedToAuth(address);
if (!isStartedRef.current) {
isStartedRef.current = true;
start();
}
}, [ address, isConnected, proceedToAuth ]);
}, [ start ]);
return <Center h="100px"><Spinner/></Center>;
};
......
import { useWeb3Modal } from '@web3modal/wagmi/react';
import React from 'react';
import { useSignMessage } from 'wagmi';
import useApiFetch from 'lib/api/useApiFetch';
import getErrorMessage from 'lib/errors/getErrorMessage';
import useToast from 'lib/hooks/useToast';
import useAccount from 'lib/web3/useAccount';
interface Props {
onSuccess?: ({ address }: { address: string }) => void;
onError?: () => void;
}
export default function useSignInWithWallet({ onSuccess, onError }: Props) {
const [ isPending, setIsPending ] = React.useState(false);
const isConnectingWalletRef = React.useRef(false);
const apiFetch = useApiFetch();
const toast = useToast();
const web3Modal = useWeb3Modal();
const { isConnected, address } = useAccount();
const { signMessageAsync } = useSignMessage();
const proceedToAuth = React.useCallback(async(address: string) => {
try {
const siweMessage = await apiFetch('auth_siwe_message', { queryParams: { address } }) as { siwe_message: string };
const signature = await signMessageAsync({ message: siweMessage.siwe_message });
await apiFetch('auth_siwe_verify', {
fetchParams: {
method: 'POST',
body: { message: siweMessage.siwe_message, signature },
},
});
onSuccess?.({ address });
} catch (error) {
// TODO @tom2drum show better error message
onError?.();
toast({
status: 'error',
title: 'Error',
description: getErrorMessage(error) || 'Something went wrong',
});
} finally {
setIsPending(false);
}
}, [ apiFetch, onError, onSuccess, signMessageAsync, toast ]);
const start = React.useCallback(() => {
setIsPending(true);
if (address) {
proceedToAuth(address);
} else {
isConnectingWalletRef.current = true;
web3Modal.open();
}
}, [ address, proceedToAuth, web3Modal ]);
React.useEffect(() => {
if (address && isConnectingWalletRef.current) {
isConnectingWalletRef.current = false;
proceedToAuth(address);
}
}, [ address, isConnected, proceedToAuth ]);
return React.useMemo(() => ({ start, isPending }), [ start, isPending ]);
}
......@@ -16,11 +16,12 @@ import { getUserHandle } from './utils';
interface Props {
profileQuery: UseQueryResult<UserInfo, unknown>;
size?: ButtonProps['size'];
variant?: 'hero' | 'header';
variant?: ButtonProps['variant'];
onClick: () => void;
isPending?: boolean;
}
const ProfileButton = ({ profileQuery, size, variant, onClick }: Props, ref: React.ForwardedRef<HTMLDivElement>) => {
const ProfileButton = ({ profileQuery, size, variant, onClick, isPending }: Props, ref: React.ForwardedRef<HTMLDivElement>) => {
const [ isFetched, setIsFetched ] = React.useState(false);
const { data, isLoading } = profileQuery;
const web3AccountWithDomain = useWeb3AccountWithDomain(!data?.address_hash);
......@@ -90,6 +91,8 @@ const ProfileButton = ({ profileQuery, size, variant, onClick }: Props, ref: Rea
lineHeight={ 5 }
px={ data ? 2.5 : 4 }
fontWeight={ data ? 700 : 600 }
isLoading={ isPending }
loadingText="Connecting"
>
{ content }
</Button>
......
import { PopoverBody, PopoverContent, PopoverTrigger, useDisclosure, type ButtonProps } from '@chakra-ui/react';
import { useRouter } from 'next/router';
import React from 'react';
import useFetchProfileInfo from 'lib/hooks/useFetchProfileInfo';
import Popover from 'ui/shared/chakra/Popover';
import AuthModal from 'ui/snippets/auth/AuthModal';
import useSignInWithWallet from 'ui/snippets/auth/screens/useSignInWithWallet';
import ProfileButton from './ProfileButton';
import ProfileMenuContent from './ProfileMenuContent';
interface Props {
buttonSize?: ButtonProps['size'];
isHomePage?: boolean;
buttonVariant?: ButtonProps['variant'];
}
const ProfileDesktop = ({ buttonSize, isHomePage }: Props) => {
const profileQuery = useFetchProfileInfo();
const ProfileDesktop = ({ buttonSize, buttonVariant = 'header' }: Props) => {
const router = useRouter();
const authModal = useDisclosure();
const profileMenu = useDisclosure();
const profileQuery = useFetchProfileInfo();
const signInWithWallet = useSignInWithWallet({});
const handleProfileButtonClick = React.useCallback(() => {
if (profileQuery.data) {
profileMenu.onOpen();
return;
}
if (router.pathname === '/apps/[id]') {
signInWithWallet.start();
return;
}
authModal.onOpen();
}, [ profileQuery.data, router.pathname, authModal, profileMenu, signInWithWallet ]);
return (
<>
<Popover openDelay={ 300 } placement="bottom-end" isLazy isOpen={ profileMenu.isOpen } onClose={ profileMenu.onClose }>
......@@ -25,8 +45,9 @@ const ProfileDesktop = ({ buttonSize, isHomePage }: Props) => {
<ProfileButton
profileQuery={ profileQuery }
size={ buttonSize }
variant={ isHomePage ? 'hero' : 'header' }
onClick={ profileQuery.data ? profileMenu.onOpen : authModal.onOpen }
variant={ buttonVariant }
onClick={ handleProfileButtonClick }
isPending={ signInWithWallet.isPending }
/>
</PopoverTrigger>
{ profileQuery.data && (
......
import { Drawer, DrawerBody, DrawerContent, DrawerOverlay, useDisclosure } from '@chakra-ui/react';
import { useRouter } from 'next/router';
import React from 'react';
import useFetchProfileInfo from 'lib/hooks/useFetchProfileInfo';
import AuthModal from 'ui/snippets/auth/AuthModal';
import useSignInWithWallet from '../auth/screens/useSignInWithWallet';
import ProfileButton from './ProfileButton';
import ProfileMenuContent from './ProfileMenuContent';
const ProfileMobile = () => {
const profileQuery = useFetchProfileInfo();
const router = useRouter();
const authModal = useDisclosure();
const profileMenu = useDisclosure();
const profileQuery = useFetchProfileInfo();
const signInWithWallet = useSignInWithWallet({});
const handleProfileButtonClick = React.useCallback(() => {
if (profileQuery.data) {
profileMenu.onOpen();
return;
}
if (router.pathname === '/apps/[id]') {
signInWithWallet.start();
return;
}
authModal.onOpen();
}, [ profileQuery.data, router.pathname, authModal, profileMenu, signInWithWallet ]);
return (
<>
<ProfileButton
profileQuery={ profileQuery }
variant="header"
onClick={ profileQuery.data ? profileMenu.onOpen : authModal.onOpen }
onClick={ handleProfileButtonClick }
/>
{ profileQuery.data && (
<Drawer
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment