diff --git a/components/email/email-composer.tsx b/components/email/email-composer.tsx index 90704e69..2401ca5c 100644 --- a/components/email/email-composer.tsx +++ b/components/email/email-composer.tsx @@ -854,6 +854,7 @@ export function EmailComposer({ return () => window.removeEventListener('keydown', handleTemplateKey); }, []); + const addFiles = useCallback(async (files: File[]) => { if (!client || files.length === 0) return; @@ -1574,6 +1575,28 @@ export function EmailComposer({ } }; + // Ctrl+Enter (Windows/Linux) / Cmd+Enter (macOS) sends the open + // compose draft — same as every other major mail client. Fires + // even when focus is inside the To/Cc/Bcc chips, subject input, + // body textarea, or the rich-text editor's contentEditable region. + // Plain Enter in the body still inserts a newline; only Enter + + // the platform modifier sends. handleSend is rebound every render, + // so we route through a ref to keep the window listener stable. + const handleSendRef = useRef<(skipAttachmentCheck?: boolean) => Promise>(); + handleSendRef.current = handleSend; + useEffect(() => { + const handleSendShortcut = (e: KeyboardEvent) => { + if (e.key !== 'Enter') return; + if (!(e.ctrlKey || e.metaKey)) return; + // Don't hijack autocomplete-confirm or chip-commit Enters. + if (e.altKey || e.shiftKey) return; + e.preventDefault(); + void handleSendRef.current?.(); + }; + window.addEventListener('keydown', handleSendShortcut); + return () => window.removeEventListener('keydown', handleSendShortcut); + }, []); + const cleanClose = () => { if (saveTimeoutRef.current) { clearTimeout(saveTimeoutRef.current); diff --git a/hooks/use-keyboard-shortcuts.ts b/hooks/use-keyboard-shortcuts.ts index 0a27942c..0dd8a841 100644 --- a/hooks/use-keyboard-shortcuts.ts +++ b/hooks/use-keyboard-shortcuts.ts @@ -290,5 +290,6 @@ export const KEYBOARD_SHORTCUTS = { ], composer: [ { key: "t", description: "shortcuts.composer.template_picker" }, + { key: "Ctrl/Cmd + Enter", description: "shortcuts.composer.send" }, ], } as const; diff --git a/locales/en/common.json b/locales/en/common.json index 072169df..0468b27e 100644 --- a/locales/en/common.json +++ b/locales/en/common.json @@ -1882,7 +1882,8 @@ "expand_collapse": "Expand/collapse thread" }, "composer": { - "template_picker": "Open template picker" + "template_picker": "Open template picker", + "send": "Send email" } }, "threads": {