diff --git a/devcon-app/next.config.js b/devcon-app/next.config.js index bfd97b182..7e5b63075 100644 --- a/devcon-app/next.config.js +++ b/devcon-app/next.config.js @@ -15,6 +15,12 @@ const nextConfig = { transpilePackages: ['@parcnet-js/podspec', '@pcd/pod'], staticPageGenerationTimeout: 300, images: { + remotePatterns: [ + { + protocol: 'https', + hostname: '**', + }, + ], domains: [ 'speak.devcon.org', 'storage.googleapis.com', diff --git a/devcon-app/src/components/domain/app/account/wallet.tsx b/devcon-app/src/components/domain/app/account/wallet.tsx index a59842777..83fa822f3 100644 --- a/devcon-app/src/components/domain/app/account/wallet.tsx +++ b/devcon-app/src/components/domain/app/account/wallet.tsx @@ -16,6 +16,7 @@ export function WalletLoginButton({ onError }: Props) { const { address } = useAccount() const { open } = useAppKit() const { signMessageAsync } = useSignMessage() + const [state, setState] = useState('') const accountContext = useAccountContext() const router = useRouter() const loggedIn = !!accountContext.account @@ -29,25 +30,40 @@ export function WalletLoginButton({ onError }: Props) { return } - const token = await accountContext.getToken(address.toLowerCase(), false) - if (!token) { - onError?.('Unable to create verification token') + let nonce = 0 + let message = '' + let signature = '' + onError?.('') + + try { + setState('Sign Message') + const token = await accountContext.getToken(address.toLowerCase(), false) + if (!token) { + onError?.('Unable to create verification token') + return + } + + nonce = token.nonce + message = createSiweMessage({ + address: address, + chainId: 1, + domain: 'app.devcon.org', + nonce: nonce.toString(), + statement: `Sign this message to prove you have access to this wallet. This won't cost you anything.`, + uri: 'https://app.devcon.org/', + version: '1', + }) + signature = await signMessageAsync({ message }) + } catch (error) { + onError?.('Unable to sign message') return + } finally { + setState('') } - const message = createSiweMessage({ - address: address, - chainId: 1, - domain: 'app.devcon.org', - nonce: token.nonce.toString(), - statement: `Sign this message to prove you have access to this wallet. This won't cost you anything.`, - uri: 'https://app.devcon.org/', - version: '1', - }) - try { - const signature = await signMessageAsync({ message }) - const userAccount = await accountContext.loginWeb3(address.toLowerCase(), token.nonce, message, signature) + setState('Connecting...') + const userAccount = await accountContext.loginWeb3(address.toLowerCase(), nonce, message, signature) if (userAccount && userAccount.onboarded) { router.push('/') return @@ -61,6 +77,8 @@ export function WalletLoginButton({ onError }: Props) { } } catch (error) { onError?.('Unable to login') + } finally { + setState('') } } @@ -85,6 +103,7 @@ export function WalletLoginButton({ onError }: Props) { fill className="w-full plain mt-4" color="purple-2" + disabled={state !== ''} onClick={(e: any) => { e.preventDefault() setTimeout(() => { @@ -92,7 +111,7 @@ export function WalletLoginButton({ onError }: Props) { }, 0) }} > - Continue With Ethereum + {state || 'Continue With Ethereum'} ) diff --git a/devcon-app/src/components/domain/app/dc7/dashboard/index.tsx b/devcon-app/src/components/domain/app/dc7/dashboard/index.tsx index 6e77ec100..135ec9e2f 100644 --- a/devcon-app/src/components/domain/app/dc7/dashboard/index.tsx +++ b/devcon-app/src/components/domain/app/dc7/dashboard/index.tsx @@ -25,6 +25,7 @@ import CalendarIcon from 'assets/icons/calendar.svg' import { Link } from 'components/common/link' import { TruncateMiddle } from 'utils/formatting' import ChevronRight from 'assets/icons/chevron_right.svg' +import { FancyLoader } from 'lib/components/loader/loader' export const cardClass = 'flex flex-col lg:border lg:border-solid lg:border-[#E4E6EB] rounded-3xl relative lg:bg-[#fbfbfb]' @@ -159,13 +160,19 @@ export const Dashboard = () => { const sessions = useRecoilValue(sessionsAtom) const draggableLink = useDraggableLink() const [_, setDevaBotVisible] = useRecoilState(devaBotVisibleAtom) - const loggedIn = accountContext.account + const { account, loading } = accountContext return (
- {loggedIn ? ( - - ) : ( + {loading && !account && ( + <> +
+ +
+ + )} + {!loading && account && } + {!loading && !account && (
@@ -185,7 +192,6 @@ export const Dashboard = () => {
)} -
Notifications
{

Go to Notifications

- -
Featured
-
{
-
- ) diff --git a/devcon-app/src/context/account-context-provider.tsx b/devcon-app/src/context/account-context-provider.tsx index 913efcffd..88bc01e75 100644 --- a/devcon-app/src/context/account-context-provider.tsx +++ b/devcon-app/src/context/account-context-provider.tsx @@ -47,6 +47,8 @@ export const AccountContextProvider = ({ children }: AccountContextProviderProps await getAccount() } catch (e) { console.log(e, 'Account fetch failed') + } finally { + setContext({ ...context, loading: false }) } } @@ -90,7 +92,7 @@ export const AccountContextProvider = ({ children }: AccountContextProviderProps const body = await response.json() if (response.status === 200) { - setContext({ ...context, account: body.data }) + setContext({ ...context, account: body.data, loading: false }) return body.data } @@ -110,7 +112,7 @@ export const AccountContextProvider = ({ children }: AccountContextProviderProps const body = await response.json() if (response.status === 200) { - setContext({ ...context, account: body.data }) + setContext({ ...context, account: body.data, loading: false }) return body.data } } @@ -127,7 +129,7 @@ export const AccountContextProvider = ({ children }: AccountContextProviderProps const body = await response.json() if (response.status === 200) { - setContext({ ...context, account: body.data }) + setContext({ ...context, account: body.data, loading: false }) return body.data } } @@ -180,7 +182,7 @@ export const AccountContextProvider = ({ children }: AccountContextProviderProps if (!response) return false if (response.status === 200) { - setContext({ ...context, account: account }) + setContext({ ...context, account: account, loading: false }) return true } @@ -202,7 +204,7 @@ export const AccountContextProvider = ({ children }: AccountContextProviderProps if (response.status === 200) { const { data } = await response.json() - setContext({ ...context, account: data }) + setContext({ ...context, account: data, loading: false }) return true } @@ -349,7 +351,14 @@ export const AccountContextProvider = ({ children }: AccountContextProviderProps You need to be logged in to personalize (and share) your schedule, track your favorite speakers, and more.

- diff --git a/devcon-app/src/pages/login/index.tsx b/devcon-app/src/pages/login/index.tsx index eb348d4fc..5d49355be 100644 --- a/devcon-app/src/pages/login/index.tsx +++ b/devcon-app/src/pages/login/index.tsx @@ -103,7 +103,7 @@ const MobileLogin = (props: any) => { type: 'spring', bounce: 0.35, }} - onClick={e => e.stopPropagation()} + onClick={(e: any) => e.stopPropagation()} className="absolute bottom-0 mx-8 bg-white max-w-[500px] min-w-[300px] self-center rounded-2xl p-4 px-4 z-20 mb-8" > @@ -121,6 +121,8 @@ const TrustModels = (props: any) => { const [error, setError] = useState('') const [email, setEmail] = useState('') const [nonce, setNonce] = useState('') + const [loading, setLoading] = useState(false) + const [resendCooldown, setResendCooldown] = useState(0) useEffect(() => { async function LoginWithToken() { @@ -140,22 +142,32 @@ const TrustModels = (props: any) => { }, [router.query.token]) const connectEmail = async () => { - if (!isEmail(email)) { - setError('Please provide a valid email address.') - return - } else { - setError('') - } + if (loading) return + + try { + setLoading(true) + if (!isEmail(email)) { + setError('Please provide a valid email address.') + return + } else { + setError('') + } - setEmailSent(true) - const token = await accountContext.getToken(email, false) - if (!token) { - setEmailSent(false) - setError('Unable to create verification token') + setEmailSent(true) + const token = await accountContext.getToken(email, false) + if (!token) { + setEmailSent(false) + setError('Unable to create verification token') + } + } finally { + setLoading(false) } } const verifyEmail = async () => { + if (loading) return + setLoading(true) + const nonceNr = Number(nonce) if (isNaN(nonceNr)) { setError('Please provide a valid verification code.') @@ -166,25 +178,46 @@ const TrustModels = (props: any) => { return } - const userAccount = await accountContext.loginEmail(email, nonceNr) - if (userAccount && userAccount.onboarded) { - router.push('/') - } - if (userAccount && !userAccount.onboarded) { - router.push('/onboarding') - } - if (!userAccount) { + try { + const userAccount = await accountContext.loginEmail(email, nonceNr) + if (userAccount && userAccount.onboarded) { + router.push('/') + } + if (userAccount && !userAccount.onboarded) { + router.push('/onboarding') + } + if (!userAccount) { + setError('Unable to verify your email address.') + } + } catch (e) { setError('Unable to verify your email address.') + } finally { + setLoading(false) } } const resendVerificationEmail = async () => { - const token = await accountContext.getToken(email, false) - if (token) { - setEmailSent(true) - } else { - setEmailSent(false) - setError('Unable to create verification token') + if (resendCooldown > 0) return + + try { + setResendCooldown(30) + const token = await accountContext.getToken(email, false) + if (token) { + setEmailSent(true) + } else { + setEmailSent(false) + setError('Unable to create verification token') + } + } finally { + const interval = setInterval(() => { + setResendCooldown(prev => { + if (prev <= 1) { + clearInterval(interval) + return 0 + } + return prev - 1 + }) + }, 1000) } } @@ -263,11 +296,12 @@ const TrustModels = (props: any) => { @@ -328,13 +362,18 @@ const TrustModels = (props: any) => { -
-
- Resend Verification Code +
0 ? 'text-gray-400' : 'text-underline cursor-pointer font-semibold' + }`} + onClick={resendVerificationEmail} + > + {resendCooldown > 0 ? `Resend in ${resendCooldown}s` : 'Resend Verification Code'}
Help?