From 5bce3745ed22260ca648bbdc30a835b1a5cd4552 Mon Sep 17 00:00:00 2001 From: Riyanshu Patro Date: Thu, 6 Feb 2025 14:05:50 +0530 Subject: [PATCH] Implement email refresh --- examples/email/src/common/common.utils.ts | 12 +++ examples/email/src/context/AppContext.tsx | 100 ++++++++++++------ .../src/modules/emailPage/EmailScreen.tsx | 32 ++++-- .../emailPage/components/EmailList.tsx | 22 ++-- examples/email/yarn.lock | 4 +- 5 files changed, 120 insertions(+), 50 deletions(-) diff --git a/examples/email/src/common/common.utils.ts b/examples/email/src/common/common.utils.ts index 50912530..1bc7aef5 100644 --- a/examples/email/src/common/common.utils.ts +++ b/examples/email/src/common/common.utils.ts @@ -137,3 +137,15 @@ export const getInCAIP = (address: string, chain: string) => { : 'push:devnet' }:${address}`; }; + +export const transformEmails = (emails: any[]) => { + return emails.map((email) => ({ + from: email.from, + to: email.to, + subject: email.subject, + timestamp: email.ts, + body: email.body.content, + attachments: email.attachments, + txHash: email.txHash, + })); +}; diff --git a/examples/email/src/context/AppContext.tsx b/examples/email/src/context/AppContext.tsx index 1b75efc9..4f46f33c 100644 --- a/examples/email/src/context/AppContext.tsx +++ b/examples/email/src/context/AppContext.tsx @@ -8,7 +8,7 @@ import { } from '@pushprotocol/pushchain-ui-kit'; import PushMail from 'push-mail'; import { ReactNode, useEffect, useState } from 'react'; -import { Email, Wallet } from '../common'; +import { Email, EMAIL_BOX, transformEmails, Wallet } from '@/common'; interface AppContextType { searchInput: string; @@ -27,8 +27,8 @@ interface AppContextType { inbox: Email[]; }> >; - currTab: 'inbox' | 'sent'; - setCurrTab: React.Dispatch>; + currTab: EMAIL_BOX; + setCurrTab: React.Dispatch>; replyTo: Email | undefined; setReplyTo: React.Dispatch>; account: string | null; @@ -36,6 +36,10 @@ interface AppContextType { wallet: Wallet | null; getEmails: () => Promise; isLoading: boolean; + getSentEmails: () => Promise; + isSentEmailLoading: boolean; + getReceivedEmails: () => Promise; + isReceivedEmailLoading: boolean; } export const AppContext = createContext(undefined); @@ -44,7 +48,8 @@ export function AppProvider({ children }: { children: ReactNode }) { const [searchInput, setSearchInput] = useState(''); const [selectedEmail, setSelectedEmail] = useState(null); const [pushNetwork, setPushNetwork] = useState(null); - const [currTab, setCurrTab] = useState<'inbox' | 'sent'>('inbox'); + const [pushEmail, setPushEmail] = useState(null); + const [currTab, setCurrTab] = useState(EMAIL_BOX.INBOX); const [emails, setEmails] = useState<{ sent: Email[]; inbox: Email[]; @@ -55,45 +60,65 @@ export function AppProvider({ children }: { children: ReactNode }) { const [replyTo, setReplyTo] = useState(undefined); const [wallet, setWallet] = useState(null); const [isLoading, setIsLoading] = useState(false); + const [isSentEmailLoading, setIsSentEmailLoading] = useState(false); + const [isReceivedEmailLoading, setIsReceivedEmailLoading] = useState(false); const { account, handleSendSignRequestToPushWallet } = usePushWalletContext(); - const getEmails = async () => { - if (!account) return; - setIsLoading(true); - const pushMail = await PushMail.initialize(ENV.DEV); - const [sent, received] = await Promise.all([ - pushMail.getBySender(account), - pushMail.getByRecipient(account), - ]); + const getSentEmails = async () => { + if (!account || !pushEmail || isLoading || isSentEmailLoading) return; + setIsSentEmailLoading(true); + try { + const sent = await pushEmail.getBySender(account); + setEmails((prev) => ({ + ...prev, + sent: transformEmails(sent), + })); + } catch (err) { + console.log('Error fetching Sent Emails', err); + } finally { + setIsSentEmailLoading(false); + } + }; - setIsLoading(false); + const getReceivedEmails = async () => { + if (!account || !pushEmail || isLoading || isReceivedEmailLoading) return; + setIsReceivedEmailLoading(true); + try { + const received = await pushEmail.getByRecipient(account); + setEmails((prev) => ({ + ...prev, + inbox: transformEmails(received), + })); + } catch (err) { + console.log('Error fetching Received Emails', err); + } finally { + setIsReceivedEmailLoading(false); + } + }; - setEmails({ - sent: sent.map((email: any) => ({ - from: email.from, - to: email.to, - subject: email.subject, - timestamp: email.ts, - body: email.body.content, - attachments: email.attachments, - txHash: email.txHash, - })), - inbox: received.map((email: any) => ({ - from: email.from, - to: email.to, - subject: email.subject, - timestamp: email.ts, - body: email.body.content, - attachments: email.attachments, - txHash: email.txHash, - })), - }); + const getEmails = async () => { + if (!account || !pushEmail || isLoading) return; + setIsLoading(true); + try { + await Promise.all([getSentEmails(), getReceivedEmails()]); + } finally { + setIsLoading(false); + } }; useEffect(() => { getEmails(); - }, [account]); + }, [account, pushEmail]); + + useEffect(() => { + const interval = setInterval(() => { + getSentEmails(); + getReceivedEmails(); + }, 5 * 60 * 1000); // 5 minutes interval + + return () => clearInterval(interval); + }); useEffect(() => { if (account) { @@ -106,8 +131,9 @@ export function AppProvider({ children }: { children: ReactNode }) { const setNetwork = async () => { try { const pushNetworkInstance = await PushNetwork.initialize(ENV.DEV); - console.log('Push Network initialized:', pushNetworkInstance); + const pushMail = await PushMail.initialize(ENV.DEV); setPushNetwork(pushNetworkInstance); + setPushEmail(pushMail); } catch (error) { console.error('Error initializing Push Network:', error); } @@ -134,6 +160,10 @@ export function AppProvider({ children }: { children: ReactNode }) { wallet, getEmails, isLoading, + getSentEmails, + isSentEmailLoading, + getReceivedEmails, + isReceivedEmailLoading, }} > {children} diff --git a/examples/email/src/modules/emailPage/EmailScreen.tsx b/examples/email/src/modules/emailPage/EmailScreen.tsx index 0bfa83a2..5c3e5ef4 100644 --- a/examples/email/src/modules/emailPage/EmailScreen.tsx +++ b/examples/email/src/modules/emailPage/EmailScreen.tsx @@ -1,4 +1,4 @@ -import { Text, Box, TextInput, Tabs } from 'shared-components'; +import { Text, Box, TextInput, Tabs, Refresh } from 'shared-components'; import { useAppContext } from '@/context/AppContext'; import { css } from 'styled-components'; import { useEffect } from 'react'; @@ -22,18 +22,26 @@ const EmailScreen = () => { setSelectedEmail, selectedEmail, replyTo, + getEmails, + getSentEmails, + getReceivedEmails, } = useAppContext(); - const handleTabSwitch = (tab: 'inbox' | 'sent') => { + const handleTabSwitch = (tab: EMAIL_BOX) => { setCurrTab(tab); + if (tab === EMAIL_BOX.INBOX) { + getReceivedEmails(); + } else { + getSentEmails(); + } // navigate(`/${tab}`); }; useEffect(() => { - if (location.pathname.includes('sent')) { - setCurrTab('sent'); + if (location.pathname.includes(EMAIL_BOX.INBOX)) { + setCurrTab(EMAIL_BOX.INBOX); } else { - setCurrTab('inbox'); + setCurrTab(EMAIL_BOX.SENT); } }, []); @@ -92,7 +100,17 @@ const EmailScreen = () => { border-bottom: 1px solid var(--stroke-secondary); `} > - Inbox + + Inbox + + + + { handleTabSwitch(tab as 'inbox' | 'sent')} + onChange={(tab) => handleTabSwitch(tab as EMAIL_BOX)} items={[ { key: 'inbox', diff --git a/examples/email/src/modules/emailPage/components/EmailList.tsx b/examples/email/src/modules/emailPage/components/EmailList.tsx index a258b890..c04d82c8 100644 --- a/examples/email/src/modules/emailPage/components/EmailList.tsx +++ b/examples/email/src/modules/emailPage/components/EmailList.tsx @@ -7,7 +7,14 @@ import { FC } from 'react'; export type EmailListProps = { type: EMAIL_BOX.INBOX | EMAIL_BOX.SENT }; const EmailList: FC = ({ type }) => { - const { searchInput, emails, isLoading } = useAppContext(); + const { + searchInput, + emails, + currTab, + isLoading, + isReceivedEmailLoading, + isSentEmailLoading, + } = useAppContext(); const filterEmails = (emails: any[], searchInput: string) => { if (searchInput === '') { @@ -30,15 +37,18 @@ const EmailList: FC = ({ type }) => { return ( - {filteredEmails.map((email, index) => ( - - ))} - {type === EMAIL_BOX.INBOX && } - {isLoading && ( + {((isLoading && isSentEmailLoading && currTab === EMAIL_BOX.SENT) || + (isLoading && + isReceivedEmailLoading && + currTab === EMAIL_BOX.INBOX)) && ( )} + {filteredEmails.map((email, index) => ( + + ))} + {type === EMAIL_BOX.INBOX && } ); diff --git a/examples/email/yarn.lock b/examples/email/yarn.lock index f61f60ec..85d964df 100644 --- a/examples/email/yarn.lock +++ b/examples/email/yarn.lock @@ -6802,7 +6802,7 @@ __metadata: "shared-components@file:../../packages/shared-components::locator=email-app%40workspace%3A.": version: 0.1.0 - resolution: "shared-components@file:../../packages/shared-components#../../packages/shared-components::hash=2a0c9e&locator=email-app%40workspace%3A." + resolution: "shared-components@file:../../packages/shared-components#../../packages/shared-components::hash=48b7a6&locator=email-app%40workspace%3A." dependencies: "@emotion/react": "npm:^11.13.0" "@radix-ui/react-dialog": "npm:^1.1.1" @@ -6823,7 +6823,7 @@ __metadata: peerDependencies: react: ^18.3.1 react-dom: ^18.3.1 - checksum: 10/087e67f0222975179d77acfb8fcf5e03e41606321966c384a224c327deca3e0543f1a1d611ebdb5e78ab93bbd209784753c406e8aeae0eaec1cb4d95dedd81b4 + checksum: 10/cb7641ef5ad6378388f0defe6b58a2153fc10da58f9fcc8014b1243fadf9ad5f09212c7f17cfdb736c2675e2d69ec4b9e079b7b12738a269adebd6104b402148 languageName: node linkType: hard