Skip to content

Commit

Permalink
Merge pull request #22 from zkemail/develop
Browse files Browse the repository at this point in the history
Add support for fetching emails from google account
  • Loading branch information
saleel authored Jul 4, 2024
2 parents a869d2f + 5b3b957 commit 0b149b6
Show file tree
Hide file tree
Showing 19 changed files with 1,757 additions and 1,118 deletions.
1 change: 1 addition & 0 deletions packages/app/.env
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
VITE_CONTRACT_ADDRESS=0x21d42CC2EcDb6db2c3D9b494D8CCcb6674360912
VITE_CIRCUIT_ARTIFACTS_URL=https://storage.googleapis.com/proof-of-twitter-artifacts/b6ea02e/
VITE_GOOGLE_CLIENT_ID=274960270901-ciaimkfeslrae1955ghq8bv7n8n3n71f.apps.googleusercontent.com
1 change: 1 addition & 0 deletions packages/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"@proof-of-twitter/circuits": "workspace:^",
"@proof-of-twitter/contracts": "workspace:^",
"@rainbow-me/rainbowkit": "^1.3.3",
"@react-oauth/google": "^0.12.1",
"@zk-email/helpers": "4.0.0",
"lodash": "^4.17.21",
"react": "^17.0.2",
Expand Down
47 changes: 47 additions & 0 deletions packages/app/src/components/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,50 @@ export const Button = styled.button`
cursor: not-allowed;
}
`;

export const OutlinedButton = styled.button`
padding: 0 14px;
border-radius: 4px;
border: none;
display: flex;
align-items: center;
justify-content: center;
font-weight: 500;
font-size: 0.9rem;
letter-spacing: -0.02em;
color: #8272e4;
cursor: pointer;
height: 48px;
width: 100%;
min-width: 32px;
transition: all 0.2s ease-in-out;
background: transparent;
border: 1px solid #8272e4;
&:hover {
background: #9b8df2;
color: white;
}
&:disabled {
opacity: 0.5;
cursor: not-allowed;
}
`;


export const TextButton = styled.button`
width: fit-content;
background: transparent;
border: none;
color: white;
font-weight: 500;
padding: 4px 16px;
border-radius: 4px;
&:hover {
background: #00000020;
color: white;
}
&:disabled {
opacity: 0.5;
cursor: not-allowed;
}
`;
35 changes: 35 additions & 0 deletions packages/app/src/components/EmailInputMethod.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { useState } from "react";
import { Button, OutlinedButton } from "./Button";

const EmailInputMethod = ({
onClickGoogle,
onClickEMLFile,
}: {
onClickGoogle: () => void;
onClickEMLFile: () => void;
}) => {
return (
<div
style={{
display: "flex",
flexDirection: "column",
justifyContent: "center",
gap: 16,
alignItems: "center",
}}
>
<Button onClick={onClickGoogle}>Sign in with Google</Button>
or
<OutlinedButton
data-testid="upload-email-eml-file-button"
onClick={() => {
onClickEMLFile();
}}
>
Upload email .eml file{" "}
</OutlinedButton>
</div>
);
};

export default EmailInputMethod;
24 changes: 24 additions & 0 deletions packages/app/src/contexts/GoogleAuth/GoogleAuthContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { createContext } from 'react'


interface GoogleAuthValues {
googleAuthToken: any | null;
isGoogleAuthed: boolean;
loggedInGmail: string | null;
scopesApproved: boolean;
googleLogIn: () => void;
googleLogOut: () => void;
}

const defaultValues: GoogleAuthValues = {
googleAuthToken: null,
isGoogleAuthed: false,
loggedInGmail: null,
scopesApproved: false,
googleLogIn: () => {},
googleLogOut: () => {},
};

const GoogleAuthContext = createContext<GoogleAuthValues>(defaultValues)

export default GoogleAuthContext
128 changes: 128 additions & 0 deletions packages/app/src/contexts/GoogleAuth/GoogleAuthProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import React, { useEffect, useState, ReactNode } from "react";
import {
hasGrantedAllScopesGoogle,
useGoogleLogin,
googleLogout,
} from "@react-oauth/google";

// import GoogleAuthContext from './GoogleAuthContext'
import { fetchProfile } from "../../hooks/useGmailClient";
import GoogleAuthContext from "./GoogleAuthContext";

interface ProvidersProps {
children: ReactNode;
}

export const esl = false;

const GoogleAuthProvider = ({ children }: ProvidersProps) => {
/*
* Contexts
*/

/*
* State Keys
*/

/*
* State
*/

const [googleAuthToken, setGoogleAuthToken] = useState<any | null>();

const [isGoogleAuthed, setIsGoogleAuthed] = useState<boolean>(false);
const [isScopesApproved, setIsScopesApproved] = useState<boolean>(false);
const [loggedInGmail, setLoggedInGmail] = useState<string | null>(null);

useEffect(() => {
esl && console.log("googleAuthScopes_1");
esl && console.log("checking googleAuthToken", googleAuthToken);

if (googleAuthToken) {
esl && console.log("googleAuthScopes_2");

const allScope = hasGrantedAllScopesGoogle(
googleAuthToken,
"email",
"profile",
"https://www.googleapis.com/auth/gmail.readonly"
);

setIsScopesApproved(allScope);
}
}, [googleAuthToken]);

useEffect(() => {
esl && console.log("googleProfile_1");
esl && console.log("checking googleAuthToken", googleAuthToken);

if (googleAuthToken) {
esl && console.log("googleProfile_2");

const fetchData = async () => {
try {
const email = await fetchProfile(googleAuthToken.access_token);

if (email) {
setLoggedInGmail(email);

localStorage.setItem("loggedInEmail", email);
}
} catch (error) {
console.error("Error in fetching profile data:", error);
}
};

fetchData();
}
}, [googleAuthToken]);

/*
* Helpers
*/

const googleLogIn = useGoogleLogin({
onSuccess: (tokenResponse) => {
setGoogleAuthToken(tokenResponse);
setIsGoogleAuthed(true);

// localStorage.setItem(
// getGoogleAuthTokenKey(),
// JSON.stringify(tokenResponse)
// );
},
scope: "email profile https://www.googleapis.com/auth/gmail.readonly",
});

const googleLogOut = () => {
setIsScopesApproved(false);

setGoogleAuthToken(null);
// localStorage.removeItem(getGoogleAuthTokenKey());

setIsGoogleAuthed(false);
localStorage.removeItem("isGoogleAuthed");

setLoggedInGmail(null);
localStorage.removeItem("loggedInGmail");

googleLogout();
};

return (
<GoogleAuthContext.Provider
value={{
googleAuthToken,
isGoogleAuthed,
loggedInGmail,
scopesApproved: isScopesApproved,
googleLogIn,
googleLogOut,
}}
>
{children}
</GoogleAuthContext.Provider>
);
};

export default GoogleAuthProvider;
2 changes: 2 additions & 0 deletions packages/app/src/contexts/GoogleAuth/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default as GoogleAuthContext } from './GoogleAuthContext'
export { default as GoogleAuthProvider } from './GoogleAuthProvider'
13 changes: 13 additions & 0 deletions packages/app/src/helpers/addressFormat.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export const formatAddress = (address: string | undefined): string => {
if (!address || address.length < 9) {
return address || '';
}
return `${address.substring(0, 6)}...${address.substring(address.length - 4)}`;
};

export const formatAddressLong = (address: string | undefined): string => {
if (!address || address.length < 9) {
return address || '';
}
return `${address.substring(0, 12)}...${address.substring(address.length - 10)}`;
};
21 changes: 21 additions & 0 deletions packages/app/src/helpers/dateTimeFormat.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export function formatDateTime(unixTimestamp: string): string {
const date = new Date(Number(unixTimestamp));
const now = new Date();

const isToday =
date.getDate() === now.getDate() &&
date.getMonth() === now.getMonth() &&
date.getFullYear() === now.getFullYear();

if (isToday) {
return date.toLocaleTimeString("en-US", {
hour: "numeric",
minute: "2-digit",
hour12: true,
});
}
return date.toLocaleDateString("en-US", {
month: "numeric",
day: "numeric",
});
}
Loading

0 comments on commit 0b149b6

Please sign in to comment.