Skip to content

Commit

Permalink
Mark emails as read
Browse files Browse the repository at this point in the history
  • Loading branch information
Shalom2212 committed Jan 7, 2024
1 parent dd6b455 commit 8a2f1ab
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 1 deletion.
45 changes: 45 additions & 0 deletions apps/web/components/ActionButtons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ import {
OrbitIcon,
ReplyIcon,
SparklesIcon,
MailCheckIcon,
MailMinusIcon,
} from "lucide-react";
import { ButtonGroup } from "@/components/ButtonGroup";
import { LoadingMiniSpinner } from "@/components/Loading";
import { getGmailUrl } from "@/utils/url";
import { onTrashThread } from "@/utils/actions-client";
import { onMarkUnmarkReadAction } from "@/utils/actions-client";

export function ActionButtons(props: {
threadId: string;
Expand All @@ -22,6 +25,7 @@ export function ActionButtons(props: {
onAiCategorize: () => void;
onReply: () => void;
onArchive: () => void;
isRead?: boolean;
refetch: () => void;
}) {
const session = useSession();
Expand All @@ -36,6 +40,7 @@ export function ActionButtons(props: {
isCategorizing,
isPlanning,
isArchiving,
isRead,
refetch,
} = props;

Expand All @@ -56,6 +61,20 @@ export function ActionButtons(props: {
setIsTrashing(false);
}, [threadId, refetch]);

const [isReadUnreading, setisReadUnreading] = useState(false);
const [isStateRead, setIsStateRead] = useState(isRead);
useMemo(() => {
setIsStateRead(isRead);
}, [isRead]);

const onReadUnread = useCallback(async () => {
setisReadUnreading(true);
await onMarkUnmarkReadAction(threadId, isStateRead);
setIsStateRead(!isStateRead);
refetch();
setisReadUnreading(false);
}, [threadId, isStateRead, refetch]);

const buttons = useMemo(
() => [
{
Expand Down Expand Up @@ -114,6 +133,31 @@ export function ActionButtons(props: {
<ArchiveIcon className="h-5 w-5 text-gray-700" aria-hidden="true" />
),
},
isStateRead
? {
tooltip: "Mark Unread",
onClick: onReadUnread,
icon: isReadUnreading ? (
<LoadingMiniSpinner />
) : (
<MailMinusIcon
className="h-5 w-5 text-gray-700"
aria-hidden="true"
/>
),
}
: {
tooltip: "Mark Read",
onClick: onReadUnread,
icon: isReadUnreading ? (
<LoadingMiniSpinner />
) : (
<MailCheckIcon
className="h-5 w-5 text-gray-700"
aria-hidden="true"
/>
),
},
],
[
onTrash,
Expand All @@ -126,6 +170,7 @@ export function ActionButtons(props: {
isCategorizing,
onReply,
openInGmail,
isStateRead,
],
);

Expand Down
1 change: 1 addition & 0 deletions apps/web/components/email-list/EmailListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ export const EmailListItem = forwardRef(
props.onArchive(thread);
props.closePanel();
}}
isRead={!isUnread}
refetch={props.refetch}
/>
</div>
Expand Down
13 changes: 12 additions & 1 deletion apps/web/components/email-list/EmailPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { type SyntheticEvent, useCallback, useMemo } from "react";
import { type SyntheticEvent, useCallback, useMemo, useState } from "react";
import { capitalCase } from "capital-case";
import { ActionButtons } from "@/components/ActionButtons";
import { Tooltip } from "@/components/Tooltip";
Expand Down Expand Up @@ -29,6 +29,15 @@ export function EmailPanel(props: {
refetch: () => void;
}) {
const lastMessage = props.row.messages?.[props.row.messages.length - 1];
const [isRead, setIsRead] = useState(false);
const isUnread = useMemo(() => {
if (lastMessage?.labelIds?.includes("UNREAD")) {
setIsRead(false);
} else {
setIsRead(true);
}
return lastMessage?.labelIds?.includes("UNREAD");
}, [lastMessage?.labelIds]);

const showReply = props.showReply;
const showThread = props.row.messages?.length > 1;
Expand Down Expand Up @@ -63,8 +72,10 @@ export function EmailPanel(props: {
props.onArchive(props.row);
props.close();
}}
isRead={!isUnread}
refetch={props.refetch}
/>

<div className="ml-2 flex items-center">
<Tooltip content="Close">
<button
Expand Down
21 changes: 21 additions & 0 deletions apps/web/utils/actions-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {
createAutoArchiveFilterAction,
deleteFilterAction,
trashThreadAction,
unMarkReadAction,
markReadAction,
} from "@/utils/actions";

export async function onAutoArchive(from: string, gmailLabelId?: string) {
Expand Down Expand Up @@ -37,3 +39,22 @@ export async function onTrashThread(threadId: string) {
});
}
}

export async function onMarkUnmarkReadAction(
threadId: string,
isRead?: boolean,
) {
try {
if (isRead) {
await unMarkReadAction(threadId);
toastSuccess({ description: "Marked Unread!" });
} else {
await markReadAction(threadId);
toastSuccess({ description: "Marked Read!" });
}
} catch (error: any) {
toastError({
description: `There was an error while marking mail: ${error.message}`,
});
}
}
28 changes: 28 additions & 0 deletions apps/web/utils/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,15 @@ import { deletePosthogUser } from "@/utils/posthog";
import { createAutoArchiveFilter, deleteFilter } from "@/utils/gmail/filter";
import { getGmailClient } from "@/utils/gmail/client";
import { trashThread } from "@/utils/gmail/trash";
import { markReadLabel, unMarkReadLabel } from "@/utils/gmail/label";
import { env } from "@/env.mjs";
import { isPremium } from "@/utils/premium";
import {
cancelUserPremium,
upgradeUserToPremium,
} from "@/utils/premium/server";
import { ChangePremiumStatusOptions } from "@/app/(app)/admin/validation";
import { threadId } from "worker_threads";

export async function createFilterFromPromptAction(body: PromptQuery) {
return createFilterFromPrompt(body);
Expand Down Expand Up @@ -59,6 +61,32 @@ export async function labelThreadsAction(options: {
);
}

export async function unMarkReadAction(threadId: string) {
const session = await auth();
if (!session?.user.id) throw new Error("Not logged in");
const gmail = getGmailClient(session);

const res = await unMarkReadLabel({
gmail: gmail,
threadId: threadId,
});

return isStatusOk(res.status) ? { ok: true } : res;
}

export async function markReadAction(threadId: string) {
const session = await auth();
if (!session?.user.id) throw new Error("Not logged in");
const gmail = getGmailClient(session);

const res = await markReadLabel({
gmail: gmail,
threadId: threadId,
});

return isStatusOk(res.status) ? { ok: true } : res;
}

// export async function archiveThreadAction(options: { threadId: string }) {
// return await archiveEmail({ id: options.threadId })
// }
Expand Down
30 changes: 30 additions & 0 deletions apps/web/utils/gmail/label.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,33 @@ export async function labelThread(options: {
},
});
}

export async function markReadLabel(options: {
gmail: gmail_v1.Gmail;
threadId: string;
}) {
const { gmail, threadId } = options;

return gmail.users.threads.modify({
userId: "me",
id: threadId,
requestBody: {
removeLabelIds: ["UNREAD"],
},
});
}

export async function unMarkReadLabel(options: {
gmail: gmail_v1.Gmail;
threadId: string;
}) {
const { gmail, threadId } = options;

return gmail.users.threads.modify({
userId: "me",
id: threadId,
requestBody: {
addLabelIds: ["UNREAD"],
},
});
}

0 comments on commit 8a2f1ab

Please sign in to comment.