diff --git a/apps/x/apps/renderer/src/App.css b/apps/x/apps/renderer/src/App.css index 0d30d94a..7d46a400 100644 --- a/apps/x/apps/renderer/src/App.css +++ b/apps/x/apps/renderer/src/App.css @@ -441,6 +441,10 @@ border-radius: 6px; } +.gmail-message-iframe-dark { + background: var(--gm-bg-card); +} + .gmail-thread-actions { display: flex; gap: 8px; diff --git a/apps/x/apps/renderer/src/components/email-view.tsx b/apps/x/apps/renderer/src/components/email-view.tsx index 3c6eb214..9839a375 100644 --- a/apps/x/apps/renderer/src/components/email-view.tsx +++ b/apps/x/apps/renderer/src/components/email-view.tsx @@ -3,6 +3,7 @@ import { Forward, LoaderIcon, RefreshCw, Reply, Search, Send } from 'lucide-reac import type { blocks } from '@x/shared' import { cn } from '@/lib/utils' import { toast } from '@/lib/toast' +import { useTheme } from '@/contexts/theme-context' type GmailThread = blocks.GmailThread type GmailThreadMessage = blocks.GmailThreadMessage @@ -115,47 +116,68 @@ function escapeHtml(text: string): string { .replace(/'/g, ''') } -function buildEmailDocument(html: string): string { +function buildEmailDocument( + html: string, + opts: { theme: 'light' | 'dark'; plainText: boolean } +): string { + const dark = opts.theme === 'dark' && opts.plainText + const colorScheme = opts.theme === 'dark' ? 'light dark' : 'light' + const bodyBg = dark ? '#131317' : 'transparent' + const bodyColor = dark ? '#d4d4d8' : '#202124' + const linkColor = dark ? '#a78bfa' : '#1a73e8' + const quoteColor = dark ? '#71717a' : '#5f6368' + const quoteBorder = dark ? '#2e2e35' : '#dadce0' + return ` + ${html}` } function MessageBody({ message, threadId }: { message: GmailThreadMessage; threadId: string }) { + const { resolvedTheme } = useTheme() const iframeRef = useRef(null) const observerRef = useRef(null) const saveTimerRef = useRef | null>(null) const lastSavedHeightRef = useRef(message.bodyHeight ?? 0) const [height, setHeight] = useState(message.bodyHeight ?? 80) + const isPlainText = !(message.bodyHtml && message.bodyHtml.trim()) + const useDarkBody = isPlainText && resolvedTheme === 'dark' + const srcDoc = useMemo(() => { if (message.bodyHtml && message.bodyHtml.trim()) { - return buildEmailDocument(message.bodyHtml) + return buildEmailDocument(message.bodyHtml, { theme: resolvedTheme, plainText: false }) } const text = (message.body || '(No message body)').trim() - return buildEmailDocument(`
${escapeHtml(text)}
`) - }, [message.bodyHtml, message.body]) + return buildEmailDocument( + `
${escapeHtml(text)}
`, + { theme: resolvedTheme, plainText: true }, + ) + }, [message.bodyHtml, message.body, resolvedTheme]) const handleLoad = useCallback(() => { const iframe = iframeRef.current @@ -195,7 +217,7 @@ function MessageBody({ message, threadId }: { message: GmailThreadMessage; threa srcDoc={srcDoc} sandbox="allow-same-origin allow-popups allow-popups-to-escape-sandbox" title="Email content" - className="gmail-message-iframe" + className={cn('gmail-message-iframe', useDarkBody && 'gmail-message-iframe-dark')} style={{ height }} onLoad={handleLoad} />