Skip to content

Commit

Permalink
Merge pull request #64 from push-protocol/add-refresh
Browse files Browse the repository at this point in the history
Implement Email refresh
  • Loading branch information
rohitmalhotra1420 authored Feb 6, 2025
2 parents f862e6e + 5bce374 commit 9bd4fd9
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 50 deletions.
12 changes: 12 additions & 0 deletions examples/email/src/common/common.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}));
};
100 changes: 65 additions & 35 deletions examples/email/src/context/AppContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -27,15 +27,19 @@ interface AppContextType {
inbox: Email[];
}>
>;
currTab: 'inbox' | 'sent';
setCurrTab: React.Dispatch<React.SetStateAction<'inbox' | 'sent'>>;
currTab: EMAIL_BOX;
setCurrTab: React.Dispatch<React.SetStateAction<EMAIL_BOX>>;
replyTo: Email | undefined;
setReplyTo: React.Dispatch<React.SetStateAction<Email | undefined>>;
account: string | null;
handleSendSignRequestToPushWallet: (data: Uint8Array) => Promise<Uint8Array>;
wallet: Wallet | null;
getEmails: () => Promise<void>;
isLoading: boolean;
getSentEmails: () => Promise<void>;
isSentEmailLoading: boolean;
getReceivedEmails: () => Promise<void>;
isReceivedEmailLoading: boolean;
}

export const AppContext = createContext<AppContextType | undefined>(undefined);
Expand All @@ -44,7 +48,8 @@ export function AppProvider({ children }: { children: ReactNode }) {
const [searchInput, setSearchInput] = useState<string>('');
const [selectedEmail, setSelectedEmail] = useState<Email | null>(null);
const [pushNetwork, setPushNetwork] = useState<PushNetwork | null>(null);
const [currTab, setCurrTab] = useState<'inbox' | 'sent'>('inbox');
const [pushEmail, setPushEmail] = useState<PushMail | null>(null);
const [currTab, setCurrTab] = useState<EMAIL_BOX>(EMAIL_BOX.INBOX);
const [emails, setEmails] = useState<{
sent: Email[];
inbox: Email[];
Expand All @@ -55,45 +60,65 @@ export function AppProvider({ children }: { children: ReactNode }) {
const [replyTo, setReplyTo] = useState<Email | undefined>(undefined);
const [wallet, setWallet] = useState<Wallet | null>(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) {
Expand All @@ -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);
}
Expand All @@ -134,6 +160,10 @@ export function AppProvider({ children }: { children: ReactNode }) {
wallet,
getEmails,
isLoading,
getSentEmails,
isSentEmailLoading,
getReceivedEmails,
isReceivedEmailLoading,
}}
>
{children}
Expand Down
32 changes: 25 additions & 7 deletions examples/email/src/modules/emailPage/EmailScreen.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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);
}
}, []);

Expand Down Expand Up @@ -92,7 +100,17 @@ const EmailScreen = () => {
border-bottom: 1px solid var(--stroke-secondary);
`}
>
<Text variant="h3-semibold">Inbox</Text>
<Box
display="flex"
justifyContent="space-between"
alignItems="center"
width="100%"
>
<Text variant="h3-semibold">Inbox</Text>
<Box cursor="pointer" onClick={getEmails}>
<Refresh size={24} />
</Box>
</Box>
<TextInput
placeholder="Search for a sender address"
value={searchInput}
Expand All @@ -104,7 +122,7 @@ const EmailScreen = () => {
<Tabs
variant="fill"
activeKey={currTab}
onChange={(tab) => handleTabSwitch(tab as 'inbox' | 'sent')}
onChange={(tab) => handleTabSwitch(tab as EMAIL_BOX)}
items={[
{
key: 'inbox',
Expand Down
22 changes: 16 additions & 6 deletions examples/email/src/modules/emailPage/components/EmailList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,14 @@ import { FC } from 'react';
export type EmailListProps = { type: EMAIL_BOX.INBOX | EMAIL_BOX.SENT };

const EmailList: FC<EmailListProps> = ({ type }) => {
const { searchInput, emails, isLoading } = useAppContext();
const {
searchInput,
emails,
currTab,
isLoading,
isReceivedEmailLoading,
isSentEmailLoading,
} = useAppContext();

const filterEmails = (emails: any[], searchInput: string) => {
if (searchInput === '') {
Expand All @@ -30,15 +37,18 @@ const EmailList: FC<EmailListProps> = ({ type }) => {
return (
<Box height="100%" width="100%" overflow="scroll">
<Box display="flex" flexDirection="column">
{filteredEmails.map((email, index) => (
<EmailCard key={index} {...email} />
))}
{type === EMAIL_BOX.INBOX && <EmailCard {...dummyEmail} />}
{isLoading && (
{((isLoading && isSentEmailLoading && currTab === EMAIL_BOX.SENT) ||
(isLoading &&
isReceivedEmailLoading &&
currTab === EMAIL_BOX.INBOX)) && (
<Box display="flex" justifyContent="center" margin="spacing-lg">
<Spinner size="medium" variant="primary" />
</Box>
)}
{filteredEmails.map((email, index) => (
<EmailCard key={index} {...email} />
))}
{type === EMAIL_BOX.INBOX && <EmailCard {...dummyEmail} />}
</Box>
</Box>
);
Expand Down
4 changes: 2 additions & 2 deletions examples/email/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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

Expand Down

0 comments on commit 9bd4fd9

Please sign in to comment.