Focus buffer scrollview instead of composer

Instead of focusing the composer, focus the buffer scrollview when
switching to a buffer. This allows keyboard navigation to work as
expected, with arrow up/down and page up/down scrolling the buffer
instead of doing nothing.

Focus back the composer when a KeyboardEvent produces text. This
allows users to start typing a message right after switching to a
buffer.

Closes: https://todo.sr.ht/~emersion/gamja/64
This commit is contained in:
Simon Ser 2021-06-22 14:44:20 +02:00
parent dc8f95c74d
commit 724d7318cf
2 changed files with 31 additions and 8 deletions

View file

@ -290,8 +290,8 @@ export default class App extends Component {
lastReadReceipt, lastReadReceipt,
}); });
if (this.composer.current) { if (this.buffer.current) {
this.composer.current.focus(); this.buffer.current.focus();
} }
if (buf.messages.length == 0) { if (buf.messages.length == 0) {
@ -1275,7 +1275,7 @@ export default class App extends Component {
scrollKey=${this.state.activeBuffer} scrollKey=${this.state.activeBuffer}
onScrollTop=${this.handleBufferScrollTop} onScrollTop=${this.handleBufferScrollTop}
> >
<section id="buffer" ref=${this.buffer}> <section id="buffer" ref=${this.buffer} tabindex="-1">
<${Buffer} <${Buffer}
buffer=${activeBuffer} buffer=${activeBuffer}
server=${activeServer} server=${activeServer}

View file

@ -58,12 +58,35 @@ export default class Composer extends Component {
} }
handleWindowKeyDown(event) { handleWindowKeyDown(event) {
if (document.activeElement === document.body && event.key === "/" && !this.state.text) { // If an <input> or <button> is focused, ignore.
event.preventDefault(); if (document.activeElement !== document.body && document.activeElement.tagName !== "SECTION") {
this.setState({ text: "/" }, () => { return;
this.focus();
});
} }
// Ignore events that don't produce a Unicode string. If the key event
// result in a character being typed by the user, KeyboardEvent.key
// will contain the typed string. The key string may contain one
// Unicode non-control character and multiple Unicode combining
// characters. String.prototype.length cannot be used since it would
// return the number of Unicode code-points. Instead, the spread
// operator is used to count the number of non-combining Unicode
// characters.
if ([...event.key].length !== 1) {
return;
}
if (this.state.text) {
return;
}
if (this.props.readOnly && event.key !== "/") {
return;
}
event.preventDefault();
this.setState({ text: event.key }, () => {
this.focus();
});
} }
componentDidMount() { componentDidMount() {