Skip to content

Commit 5bce374

Browse files
Implement email refresh
1 parent f862e6e commit 5bce374

File tree

5 files changed

+120
-50
lines changed

5 files changed

+120
-50
lines changed

examples/email/src/common/common.utils.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,3 +137,15 @@ export const getInCAIP = (address: string, chain: string) => {
137137
: 'push:devnet'
138138
}:${address}`;
139139
};
140+
141+
export const transformEmails = (emails: any[]) => {
142+
return emails.map((email) => ({
143+
from: email.from,
144+
to: email.to,
145+
subject: email.subject,
146+
timestamp: email.ts,
147+
body: email.body.content,
148+
attachments: email.attachments,
149+
txHash: email.txHash,
150+
}));
151+
};

examples/email/src/context/AppContext.tsx

Lines changed: 65 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
} from '@pushprotocol/pushchain-ui-kit';
99
import PushMail from 'push-mail';
1010
import { ReactNode, useEffect, useState } from 'react';
11-
import { Email, Wallet } from '../common';
11+
import { Email, EMAIL_BOX, transformEmails, Wallet } from '@/common';
1212

1313
interface AppContextType {
1414
searchInput: string;
@@ -27,15 +27,19 @@ interface AppContextType {
2727
inbox: Email[];
2828
}>
2929
>;
30-
currTab: 'inbox' | 'sent';
31-
setCurrTab: React.Dispatch<React.SetStateAction<'inbox' | 'sent'>>;
30+
currTab: EMAIL_BOX;
31+
setCurrTab: React.Dispatch<React.SetStateAction<EMAIL_BOX>>;
3232
replyTo: Email | undefined;
3333
setReplyTo: React.Dispatch<React.SetStateAction<Email | undefined>>;
3434
account: string | null;
3535
handleSendSignRequestToPushWallet: (data: Uint8Array) => Promise<Uint8Array>;
3636
wallet: Wallet | null;
3737
getEmails: () => Promise<void>;
3838
isLoading: boolean;
39+
getSentEmails: () => Promise<void>;
40+
isSentEmailLoading: boolean;
41+
getReceivedEmails: () => Promise<void>;
42+
isReceivedEmailLoading: boolean;
3943
}
4044

4145
export const AppContext = createContext<AppContextType | undefined>(undefined);
@@ -44,7 +48,8 @@ export function AppProvider({ children }: { children: ReactNode }) {
4448
const [searchInput, setSearchInput] = useState<string>('');
4549
const [selectedEmail, setSelectedEmail] = useState<Email | null>(null);
4650
const [pushNetwork, setPushNetwork] = useState<PushNetwork | null>(null);
47-
const [currTab, setCurrTab] = useState<'inbox' | 'sent'>('inbox');
51+
const [pushEmail, setPushEmail] = useState<PushMail | null>(null);
52+
const [currTab, setCurrTab] = useState<EMAIL_BOX>(EMAIL_BOX.INBOX);
4853
const [emails, setEmails] = useState<{
4954
sent: Email[];
5055
inbox: Email[];
@@ -55,45 +60,65 @@ export function AppProvider({ children }: { children: ReactNode }) {
5560
const [replyTo, setReplyTo] = useState<Email | undefined>(undefined);
5661
const [wallet, setWallet] = useState<Wallet | null>(null);
5762
const [isLoading, setIsLoading] = useState(false);
63+
const [isSentEmailLoading, setIsSentEmailLoading] = useState(false);
64+
const [isReceivedEmailLoading, setIsReceivedEmailLoading] = useState(false);
5865

5966
const { account, handleSendSignRequestToPushWallet } = usePushWalletContext();
6067

61-
const getEmails = async () => {
62-
if (!account) return;
63-
setIsLoading(true);
64-
const pushMail = await PushMail.initialize(ENV.DEV);
65-
const [sent, received] = await Promise.all([
66-
pushMail.getBySender(account),
67-
pushMail.getByRecipient(account),
68-
]);
68+
const getSentEmails = async () => {
69+
if (!account || !pushEmail || isLoading || isSentEmailLoading) return;
70+
setIsSentEmailLoading(true);
71+
try {
72+
const sent = await pushEmail.getBySender(account);
73+
setEmails((prev) => ({
74+
...prev,
75+
sent: transformEmails(sent),
76+
}));
77+
} catch (err) {
78+
console.log('Error fetching Sent Emails', err);
79+
} finally {
80+
setIsSentEmailLoading(false);
81+
}
82+
};
6983

70-
setIsLoading(false);
84+
const getReceivedEmails = async () => {
85+
if (!account || !pushEmail || isLoading || isReceivedEmailLoading) return;
86+
setIsReceivedEmailLoading(true);
87+
try {
88+
const received = await pushEmail.getByRecipient(account);
89+
setEmails((prev) => ({
90+
...prev,
91+
inbox: transformEmails(received),
92+
}));
93+
} catch (err) {
94+
console.log('Error fetching Received Emails', err);
95+
} finally {
96+
setIsReceivedEmailLoading(false);
97+
}
98+
};
7199

72-
setEmails({
73-
sent: sent.map((email: any) => ({
74-
from: email.from,
75-
to: email.to,
76-
subject: email.subject,
77-
timestamp: email.ts,
78-
body: email.body.content,
79-
attachments: email.attachments,
80-
txHash: email.txHash,
81-
})),
82-
inbox: received.map((email: any) => ({
83-
from: email.from,
84-
to: email.to,
85-
subject: email.subject,
86-
timestamp: email.ts,
87-
body: email.body.content,
88-
attachments: email.attachments,
89-
txHash: email.txHash,
90-
})),
91-
});
100+
const getEmails = async () => {
101+
if (!account || !pushEmail || isLoading) return;
102+
setIsLoading(true);
103+
try {
104+
await Promise.all([getSentEmails(), getReceivedEmails()]);
105+
} finally {
106+
setIsLoading(false);
107+
}
92108
};
93109

94110
useEffect(() => {
95111
getEmails();
96-
}, [account]);
112+
}, [account, pushEmail]);
113+
114+
useEffect(() => {
115+
const interval = setInterval(() => {
116+
getSentEmails();
117+
getReceivedEmails();
118+
}, 5 * 60 * 1000); // 5 minutes interval
119+
120+
return () => clearInterval(interval);
121+
});
97122

98123
useEffect(() => {
99124
if (account) {
@@ -106,8 +131,9 @@ export function AppProvider({ children }: { children: ReactNode }) {
106131
const setNetwork = async () => {
107132
try {
108133
const pushNetworkInstance = await PushNetwork.initialize(ENV.DEV);
109-
console.log('Push Network initialized:', pushNetworkInstance);
134+
const pushMail = await PushMail.initialize(ENV.DEV);
110135
setPushNetwork(pushNetworkInstance);
136+
setPushEmail(pushMail);
111137
} catch (error) {
112138
console.error('Error initializing Push Network:', error);
113139
}
@@ -134,6 +160,10 @@ export function AppProvider({ children }: { children: ReactNode }) {
134160
wallet,
135161
getEmails,
136162
isLoading,
163+
getSentEmails,
164+
isSentEmailLoading,
165+
getReceivedEmails,
166+
isReceivedEmailLoading,
137167
}}
138168
>
139169
{children}

examples/email/src/modules/emailPage/EmailScreen.tsx

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Text, Box, TextInput, Tabs } from 'shared-components';
1+
import { Text, Box, TextInput, Tabs, Refresh } from 'shared-components';
22
import { useAppContext } from '@/context/AppContext';
33
import { css } from 'styled-components';
44
import { useEffect } from 'react';
@@ -22,18 +22,26 @@ const EmailScreen = () => {
2222
setSelectedEmail,
2323
selectedEmail,
2424
replyTo,
25+
getEmails,
26+
getSentEmails,
27+
getReceivedEmails,
2528
} = useAppContext();
2629

27-
const handleTabSwitch = (tab: 'inbox' | 'sent') => {
30+
const handleTabSwitch = (tab: EMAIL_BOX) => {
2831
setCurrTab(tab);
32+
if (tab === EMAIL_BOX.INBOX) {
33+
getReceivedEmails();
34+
} else {
35+
getSentEmails();
36+
}
2937
// navigate(`/${tab}`);
3038
};
3139

3240
useEffect(() => {
33-
if (location.pathname.includes('sent')) {
34-
setCurrTab('sent');
41+
if (location.pathname.includes(EMAIL_BOX.INBOX)) {
42+
setCurrTab(EMAIL_BOX.INBOX);
3543
} else {
36-
setCurrTab('inbox');
44+
setCurrTab(EMAIL_BOX.SENT);
3745
}
3846
}, []);
3947

@@ -92,7 +100,17 @@ const EmailScreen = () => {
92100
border-bottom: 1px solid var(--stroke-secondary);
93101
`}
94102
>
95-
<Text variant="h3-semibold">Inbox</Text>
103+
<Box
104+
display="flex"
105+
justifyContent="space-between"
106+
alignItems="center"
107+
width="100%"
108+
>
109+
<Text variant="h3-semibold">Inbox</Text>
110+
<Box cursor="pointer" onClick={getEmails}>
111+
<Refresh size={24} />
112+
</Box>
113+
</Box>
96114
<TextInput
97115
placeholder="Search for a sender address"
98116
value={searchInput}
@@ -104,7 +122,7 @@ const EmailScreen = () => {
104122
<Tabs
105123
variant="fill"
106124
activeKey={currTab}
107-
onChange={(tab) => handleTabSwitch(tab as 'inbox' | 'sent')}
125+
onChange={(tab) => handleTabSwitch(tab as EMAIL_BOX)}
108126
items={[
109127
{
110128
key: 'inbox',

examples/email/src/modules/emailPage/components/EmailList.tsx

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,14 @@ import { FC } from 'react';
77
export type EmailListProps = { type: EMAIL_BOX.INBOX | EMAIL_BOX.SENT };
88

99
const EmailList: FC<EmailListProps> = ({ type }) => {
10-
const { searchInput, emails, isLoading } = useAppContext();
10+
const {
11+
searchInput,
12+
emails,
13+
currTab,
14+
isLoading,
15+
isReceivedEmailLoading,
16+
isSentEmailLoading,
17+
} = useAppContext();
1118

1219
const filterEmails = (emails: any[], searchInput: string) => {
1320
if (searchInput === '') {
@@ -30,15 +37,18 @@ const EmailList: FC<EmailListProps> = ({ type }) => {
3037
return (
3138
<Box height="100%" width="100%" overflow="scroll">
3239
<Box display="flex" flexDirection="column">
33-
{filteredEmails.map((email, index) => (
34-
<EmailCard key={index} {...email} />
35-
))}
36-
{type === EMAIL_BOX.INBOX && <EmailCard {...dummyEmail} />}
37-
{isLoading && (
40+
{((isLoading && isSentEmailLoading && currTab === EMAIL_BOX.SENT) ||
41+
(isLoading &&
42+
isReceivedEmailLoading &&
43+
currTab === EMAIL_BOX.INBOX)) && (
3844
<Box display="flex" justifyContent="center" margin="spacing-lg">
3945
<Spinner size="medium" variant="primary" />
4046
</Box>
4147
)}
48+
{filteredEmails.map((email, index) => (
49+
<EmailCard key={index} {...email} />
50+
))}
51+
{type === EMAIL_BOX.INBOX && <EmailCard {...dummyEmail} />}
4252
</Box>
4353
</Box>
4454
);

examples/email/yarn.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6802,7 +6802,7 @@ __metadata:
68026802

68036803
"shared-components@file:../../packages/shared-components::locator=email-app%40workspace%3A.":
68046804
version: 0.1.0
6805-
resolution: "shared-components@file:../../packages/shared-components#../../packages/shared-components::hash=2a0c9e&locator=email-app%40workspace%3A."
6805+
resolution: "shared-components@file:../../packages/shared-components#../../packages/shared-components::hash=48b7a6&locator=email-app%40workspace%3A."
68066806
dependencies:
68076807
"@emotion/react": "npm:^11.13.0"
68086808
"@radix-ui/react-dialog": "npm:^1.1.1"
@@ -6823,7 +6823,7 @@ __metadata:
68236823
peerDependencies:
68246824
react: ^18.3.1
68256825
react-dom: ^18.3.1
6826-
checksum: 10/087e67f0222975179d77acfb8fcf5e03e41606321966c384a224c327deca3e0543f1a1d611ebdb5e78ab93bbd209784753c406e8aeae0eaec1cb4d95dedd81b4
6826+
checksum: 10/cb7641ef5ad6378388f0defe6b58a2153fc10da58f9fcc8014b1243fadf9ad5f09212c7f17cfdb736c2675e2d69ec4b9e079b7b12738a269adebd6104b402148
68276827
languageName: node
68286828
linkType: hard
68296829

0 commit comments

Comments
 (0)