-
Notifications
You must be signed in to change notification settings - Fork 1.2k
AI generate reply / nudge endpoints #330
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
64fdcf4
Ai generate reply / nudge endpoints
elie222 d3072f8
Move stringify email to utils
elie222 37097d4
refactor get-email-from-message
elie222 aec6cd3
Use internalDate for server side tasks
elie222 d3d6e6c
Update AI packages
elie222 484229c
stream nudge
elie222 061cad9
dont stream text response
elie222 396def0
move ai nudge to action
elie222 e610ef9
cache nudge
elie222 b802893
break down email thread into smaller components
elie222 7238346
improve scrolling on reply tracker
elie222 1687a74
Show AI generated replies
elie222 31cfde5
fix spinner
elie222 031988d
fix nudge new lines
elie222 451fc2b
skip generate button
elie222 98b0c48
Adjust prompt
elie222 1a67166
Update copy
elie222 de03f92
improve reply tracker spacing
elie222 49dc871
clearer search params
elie222 d186e8d
remove swrprovider check
elie222 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| import { Card } from "@/components/Card"; | ||
| import { Button } from "@/components/ui/button"; | ||
| import Link from "next/link"; | ||
| import { DownloadIcon } from "lucide-react"; | ||
| import type { ThreadMessage } from "@/components/email-list/types"; | ||
|
|
||
| export function EmailAttachments({ message }: { message: ThreadMessage }) { | ||
| return ( | ||
| <div className="mt-4 grid grid-cols-2 gap-2 xl:grid-cols-3"> | ||
| {message.attachments?.map((attachment) => { | ||
| const searchParams = new URLSearchParams({ | ||
| messageId: message.id, | ||
| attachmentId: attachment.attachmentId, | ||
| mimeType: attachment.mimeType, | ||
| filename: attachment.filename, | ||
| }); | ||
|
|
||
| const url = `/api/google/messages/attachment?${searchParams.toString()}`; | ||
|
|
||
| return ( | ||
| <Card key={attachment.filename} className="p-4"> | ||
| <div className="text-gray-600">{attachment.filename}</div> | ||
| <div className="mt-4 flex items-center justify-between"> | ||
| <div className="text-gray-600"> | ||
| {mimeTypeToString(attachment.mimeType)} | ||
| </div> | ||
| <Button variant="outline" size="sm" asChild> | ||
| <Link href={url} target="_blank"> | ||
| <> | ||
| <DownloadIcon className="mr-2 h-4 w-4" /> | ||
| Download | ||
| </> | ||
| </Link> | ||
| </Button> | ||
| </div> | ||
| </Card> | ||
| ); | ||
| })} | ||
| </div> | ||
| ); | ||
| } | ||
|
|
||
| function mimeTypeToString(mimeType: string): string { | ||
| switch (mimeType) { | ||
| case "application/pdf": | ||
| return "PDF"; | ||
| case "application/zip": | ||
| return "ZIP"; | ||
| case "image/png": | ||
| return "PNG"; | ||
| case "image/jpeg": | ||
| return "JPEG"; | ||
| // LLM generated. Need to check they're actually needed | ||
| case "application/vnd.openxmlformats-officedocument.wordprocessingml.document": | ||
| return "DOCX"; | ||
| case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": | ||
| return "XLSX"; | ||
| case "application/vnd.openxmlformats-officedocument.presentationml.presentation": | ||
| return "PPTX"; | ||
| case "application/vnd.ms-excel": | ||
| return "XLS"; | ||
| case "application/vnd.ms-powerpoint": | ||
| return "PPT"; | ||
| case "application/msword": | ||
| return "DOC"; | ||
| default: | ||
| return mimeType; | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| import { type SyntheticEvent, useCallback, useMemo, useState } from "react"; | ||
| import { Loading } from "@/components/Loading"; | ||
|
|
||
| export function HtmlEmail({ html }: { html: string }) { | ||
| const srcDoc = useMemo(() => getIframeHtml(html), [html]); | ||
| const [isLoading, setIsLoading] = useState(true); | ||
|
|
||
| const onLoad = useCallback( | ||
| (event: SyntheticEvent<HTMLIFrameElement, Event>) => { | ||
| if (event.currentTarget.contentWindow) { | ||
| // sometimes we see minimal scrollbar, so add a buffer | ||
| const BUFFER = 5; | ||
|
|
||
| const height = `${ | ||
| event.currentTarget.contentWindow.document.documentElement | ||
| .scrollHeight + BUFFER | ||
| }px`; | ||
|
|
||
| event.currentTarget.style.height = height; | ||
| setIsLoading(false); | ||
| } | ||
| }, | ||
| [], | ||
| ); | ||
|
|
||
| return ( | ||
| <div> | ||
| {isLoading && <Loading />} | ||
| <iframe | ||
| srcDoc={srcDoc} | ||
| onLoad={onLoad} | ||
| className="h-0 min-h-0 w-full" | ||
| title="Email content preview" | ||
| /> | ||
| </div> | ||
| ); | ||
| } | ||
elie222 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| export function PlainEmail({ text }: { text: string }) { | ||
| return <pre className="whitespace-pre-wrap">{text}</pre>; | ||
| } | ||
|
|
||
| function getIframeHtml(html: string) { | ||
| // Always inject our default font styles with lower specificity | ||
| // This ensures styled elements keep their fonts while unstyled ones get our defaults | ||
| const defaultFontStyles = ` | ||
| <style> | ||
| /* Base styles with low specificity */ | ||
| body { | ||
| font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; | ||
| margin: 0; | ||
| } | ||
| </style> | ||
| `; | ||
|
|
||
| let htmlWithHead = ""; | ||
| if (html.indexOf("</head>") === -1) { | ||
| htmlWithHead = `<head>${defaultFontStyles}<base target="_blank"></head>${html}`; | ||
| } else { | ||
| htmlWithHead = html.replace( | ||
| "</head>", | ||
| `${defaultFontStyles}<base target="_blank" rel="noopener noreferrer"></head>`, | ||
| ); | ||
| } | ||
|
|
||
| return htmlWithHead; | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| import type { ThreadMessage } from "@/components/email-list/types"; | ||
|
|
||
| export function EmailDetails({ message }: { message: ThreadMessage }) { | ||
| const details = [ | ||
| { label: "From", value: message.headers.from }, | ||
| { label: "To", value: message.headers.to }, | ||
| { label: "CC", value: message.headers.cc }, | ||
| { label: "BCC", value: message.headers.bcc }, | ||
| { | ||
| label: "Date", | ||
| value: new Date(message.headers.date).toLocaleString(), | ||
| }, | ||
| // { label: "Subject", value: message.headers.subject }, | ||
| ]; | ||
|
|
||
| return ( | ||
| <div className="mb-4 rounded-md bg-gray-50 p-3 text-sm"> | ||
| <div className="grid gap-1"> | ||
| {details.map( | ||
| ({ label, value }) => | ||
| value && ( | ||
| <div key={label} className="grid grid-cols-[auto,1fr] gap-2"> | ||
| <span className="font-medium">{label}:</span> | ||
| <span>{value}</span> | ||
| </div> | ||
| ), | ||
| )} | ||
| </div> | ||
| </div> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.