Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Focus on composition area when pressing a key #4998

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions ts/components/CompositionArea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,37 @@ export const CompositionArea = ({
};
}, [setLarge]);

// Listen to any key in the conversation panel to

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Listen to any key in the conversation panel to
// Focus message composition input when key is pressed

React.useEffect(() => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

useEffect has now been imported as a named import

Suggested change
React.useEffect(() => {
useEffect(() => {

const handler = (e: KeyboardEvent) => {
const { key } = e;

// We don't want to react to a control character
if (key.length !== 1) {
return;
}

// We don't want to switch focus if another panel is up
const panels = document.querySelectorAll('.conversation .panel');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also these kind of class lookups are brittle, if we ever change conversation | panel this would fall apart. I think ideally redux would know about panel state and we can just query that selector if there are panels active or not.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this information already saved in a Redux store somewhere? Or are you implying that it should be added? (And if you're suggesting it be added, where would be your suggestion for where to add this?)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, seems like this already has precedent in the codebase:

const panels = document.querySelectorAll('.conversation .panel');
if (panels && panels.length > 1) {
return;
}

Maybe refactoring this could be done in a different PR?

if (panels && panels.length > 1) {
return;
}

// We don't want to take focus away of input fields
Copy link

@karlhorky karlhorky Oct 30, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clarity:

Suggested change
// We don't want to take focus away of input fields
// Avoid stealing focus from focused input fields

const { activeElement } = document;
if (activeElement?.nodeName.toLowerCase() === 'input') {
Comment on lines +377 to +378

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style: Avoid extra identifier in scope

Suggested change
const { activeElement } = document;
if (activeElement?.nodeName.toLowerCase() === 'input') {
if (document.activeElement?.nodeName.toLowerCase() === 'input') {

return;
}

inputApiRef.current?.focus();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this use the focusInput callback instead?

If yes, then:

Suggested change
inputApiRef.current?.focus();
focusInput();

};

document.addEventListener('keydown', handler);
return () => {
document.removeEventListener('keydown', handler);
};
Comment on lines +385 to +388

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Surfacing @josh-signal's comment here in a conversation:

It's adding the event listener to document so yeah it's grabbing all input. Perhaps a better safer approach would be to figure out what node is focused and listen to keypress on that node? I think we can test the "in focus" issue using something like macOS' spaces.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@josh-signal to be clear, you're suggesting this change?

Suggested change
document.addEventListener('keydown', handler);
return () => {
document.removeEventListener('keydown', handler);
};
document.activeElement.addEventListener('keypress', handler);
return () => {
document.activeElement.removeEventListener('keypress', handler);
};

Not sure if this will work, but at least it's a starting place for the conversation.

});

if (
isBlocked ||
areWePending ||
Expand Down