CI / Build & Quality Checks (push) Successful in 1m47s
CI / Docker image build & smoke test (push) Skipped
CI / Secret scan (gitleaks) (push) Successful in 7s
CI / Trigger Desktop Build (push) Canceled after 0s
CI / Playwright smoke (e2e) (push) Canceled after 0s
With the mention list open, pressing Enter sent the half-typed text
("hey @bo") instead of inserting the highlighted person — found while
investigating the "composer hit a snag" report; only Tab picked. Enter now
picks the top suggestion for people, rooms and commands, as in Discord,
Slack and Element.
useAutocompleteEnter listens in the window capture phase (so it runs before
the composer's submit handler) and only while the list has suggestions —
with no command match Enter still sends. Emoji suggestions are deliberately
left on Tab only, so "lol :p" + Enter still sends rather than inserting an
emoji. IME composition and Shift/Ctrl+Enter are untouched. Tab now inserts
the member's display name, same as a click.
Verified: "@bo" + Enter inserts the mention and sends nothing; the next
Enter sends "hey @bob hi" with m.mentions; ":smi" + Enter still sends.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
29 lines
1.1 KiB
TypeScript
29 lines
1.1 KiB
TypeScript
import { useEffect, useRef } from 'react';
|
|
import { isKeyHotkey } from 'is-hotkey';
|
|
|
|
/**
|
|
* Enter picks the top suggestion while an autocomplete list is showing, as in
|
|
* Discord / Slack / Element, instead of sending the half-typed text ("hey @bo").
|
|
*
|
|
* The listener runs in the window's capture phase so it sees Enter before the
|
|
* composer's own handler (which would submit), and only claims the key when
|
|
* `active` (the list has suggestions) — otherwise Enter sends as normal. IME
|
|
* composition and modified Enter (Shift/Ctrl/Alt/Meta) are left alone.
|
|
*/
|
|
export function useAutocompleteEnter(active: boolean, onSelect: () => void): void {
|
|
const selectRef = useRef(onSelect);
|
|
selectRef.current = onSelect;
|
|
|
|
useEffect(() => {
|
|
if (!active) return undefined;
|
|
const onKeyDown = (evt: KeyboardEvent) => {
|
|
if (evt.isComposing || !isKeyHotkey('enter', evt)) return;
|
|
evt.preventDefault();
|
|
evt.stopPropagation();
|
|
selectRef.current();
|
|
};
|
|
window.addEventListener('keydown', onKeyDown, true);
|
|
return () => window.removeEventListener('keydown', onKeyDown, true);
|
|
}, [active]);
|
|
}
|