Merge branch 'main' into fix/message-drag-blob-routing

This commit is contained in:
Linus Rath
2026-10-20 22:22:13 +02:00
committed by GitHub
2 changed files with 20 additions and 14 deletions
@@ -518,17 +518,19 @@ describe('composer-sidebar and composer-sidebar-right', () => {
offerSlots('p1', ['composer-sidebar', 'composer-sidebar-right']);
const { unmount } = render(<EmailComposer initialData={DRAFT} onClose={vi.fn()} />);
// A mouse drag, as pointer events with the button held (the handle follows pointers).
const drag = (handle: HTMLElement, from: number, to: number) => {
fireEvent.pointerDown(handle, { pointerId: 1, button: 0, buttons: 1, pointerType: 'mouse', clientX: from, clientY: 10 });
fireEvent.pointerMove(document, { pointerId: 1, buttons: 1, pointerType: 'mouse', clientX: to, clientY: 10 });
fireEvent.pointerUp(document, { pointerId: 1, button: 0, buttons: 0, pointerType: 'mouse' });
};
// The right panel's handle is on its left edge: dragging left widens it.
const right = screen.getByTestId('composer-sidebar-resize-right');
fireEvent.mouseDown(right, { clientX: 1000 });
fireEvent.mouseMove(document, { clientX: 900 });
fireEvent.mouseUp(document);
drag(right, 1000, 900);
expect(panel('right').style.width).toBe('360px');
// The left panel's handle is on its right edge: dragging left narrows it, down to the minimum.
const left = screen.getByTestId('composer-sidebar-resize-left');
fireEvent.mouseDown(left, { clientX: 300 });
fireEvent.mouseMove(document, { clientX: 100 });
fireEvent.mouseUp(document);
drag(left, 300, 100);
expect(panel('left').style.width).toBe('220px');
fireEvent.keyDown(left, { key: 'ArrowRight' });
expect(panel('left').style.width).toBe('230px');
+12 -8
View File
@@ -2753,6 +2753,17 @@ export function EmailComposer({
const wantsPluginSelection = wantsPluginDraft;
const [pluginSelection, setPluginSelection] = useState<{ text: string; empty: boolean }>(EMPTY_SELECTION);
const [pluginEditor, setPluginEditor] = useState<Editor | null>(null);
// One callback for the composer's life: the editor reports itself ready
// whenever this changes, and every report now sets state, so a new arrow
// per render would report, render and report again without end.
const handleEditorReady = useCallback((ed: Editor) => {
editorRef.current = ed;
setPluginEditor(ed);
if (!replyFocusedRef.current && (mode === 'reply' || mode === 'replyAll')) {
replyFocusedRef.current = true;
ed.commands.focus('start');
}
}, [mode]);
useEffect(() => {
if (!wantsPluginSelection) return;
let timer: ReturnType<typeof setTimeout> | null = null;
@@ -4158,14 +4169,7 @@ export function EmailComposer({
hasError={validationErrors.body}
collapseToolbarOnMobile={!showFormattingOnMobile}
toolbarPlacement={mvWindow ? (mvShowFormatting ? 'bottom' : 'hidden') : 'top'}
onEditorReady={(ed) => {
editorRef.current = ed;
setPluginEditor(ed);
if (!replyFocusedRef.current && (mode === 'reply' || mode === 'replyAll')) {
replyFocusedRef.current = true;
ed.commands.focus('start');
}
}}
onEditorReady={handleEditorReady}
mentionCandidates={recipientMentionsEnabled ? mentionCandidates : undefined}
findMentionContacts={recipientMentionsEnabled && mentionAddsRecipientTo !== 'off' ? findMentionContacts : undefined}
mentionAddsTo={mentionAddsRecipientTo === 'cc' ? 'cc' : 'to'}