fix: scope Ctrl/Cmd+Enter send to focused composer
This commit is contained in:
@@ -854,7 +854,6 @@ export function EmailComposer({
|
|||||||
return () => window.removeEventListener('keydown', handleTemplateKey);
|
return () => window.removeEventListener('keydown', handleTemplateKey);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
const addFiles = useCallback(async (files: File[]) => {
|
const addFiles = useCallback(async (files: File[]) => {
|
||||||
if (!client || files.length === 0) return;
|
if (!client || files.length === 0) return;
|
||||||
|
|
||||||
@@ -1575,21 +1574,23 @@ export function EmailComposer({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Ctrl+Enter (Windows/Linux) / Cmd+Enter (macOS) sends the open
|
// Ctrl+Enter (Win/Linux) / Cmd+Enter (macOS) sends the open compose
|
||||||
// compose draft — same as every other major mail client. Fires
|
// draft. Scoped to events whose target lives inside this composer's
|
||||||
// even when focus is inside the To/Cc/Bcc chips, subject input,
|
// DOM tree — in Pro mode multiple composer tabs can be mounted at
|
||||||
// body textarea, or the rich-text editor's contentEditable region.
|
// once (inactive tabs are CSS-hidden, not unmounted), so a window
|
||||||
// Plain Enter in the body still inserts a newline; only Enter +
|
// listener would otherwise fire every mounted composer's handleSend
|
||||||
// the platform modifier sends. handleSend is rebound every render,
|
// on a single keystroke. handleSend is rebound every render, so we
|
||||||
// so we route through a ref to keep the window listener stable.
|
// route through a ref to keep the listener stable.
|
||||||
const handleSendRef = useRef<(skipAttachmentCheck?: boolean) => Promise<void>>();
|
const composerRootRef = useRef<HTMLDivElement | null>(null);
|
||||||
|
const handleSendRef = useRef<((skipAttachmentCheck?: boolean) => Promise<void>) | undefined>(undefined);
|
||||||
handleSendRef.current = handleSend;
|
handleSendRef.current = handleSend;
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleSendShortcut = (e: KeyboardEvent) => {
|
const handleSendShortcut = (e: KeyboardEvent) => {
|
||||||
if (e.key !== 'Enter') return;
|
if (e.key !== 'Enter') return;
|
||||||
if (!(e.ctrlKey || e.metaKey)) return;
|
if (!(e.ctrlKey || e.metaKey)) return;
|
||||||
// Don't hijack autocomplete-confirm or chip-commit Enters.
|
|
||||||
if (e.altKey || e.shiftKey) return;
|
if (e.altKey || e.shiftKey) return;
|
||||||
|
const root = composerRootRef.current;
|
||||||
|
if (!root || !(e.target instanceof Node) || !root.contains(e.target)) return;
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
void handleSendRef.current?.();
|
void handleSendRef.current?.();
|
||||||
};
|
};
|
||||||
@@ -1636,7 +1637,7 @@ export function EmailComposer({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={cn("flex h-full bg-background", className)}>
|
<div ref={composerRootRef} className={cn("flex h-full bg-background", className)}>
|
||||||
<PluginSlot
|
<PluginSlot
|
||||||
name="composer-sidebar"
|
name="composer-sidebar"
|
||||||
className="hidden md:flex shrink-0 h-full overflow-hidden border-r border-border"
|
className="hidden md:flex shrink-0 h-full overflow-hidden border-r border-border"
|
||||||
|
|||||||
Reference in New Issue
Block a user