~emersion/gamja

724d7318cf7f9122a6d5dacec7870da3c3e2f78a — Simon Ser 5 months ago dc8f95c
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
2 files changed, 31 insertions(+), 8 deletions(-)

M components/app.js
M components/composer.js
M components/app.js => components/app.js +3 -3
@@ 290,8 290,8 @@ export default class App extends Component {
				lastReadReceipt,
			});

			if (this.composer.current) {
				this.composer.current.focus();
			if (this.buffer.current) {
				this.buffer.current.focus();
			}

			if (buf.messages.length == 0) {


@@ 1275,7 1275,7 @@ export default class App extends Component {
				scrollKey=${this.state.activeBuffer}
				onScrollTop=${this.handleBufferScrollTop}
			>
				<section id="buffer" ref=${this.buffer}>
				<section id="buffer" ref=${this.buffer} tabindex="-1">
					<${Buffer}
						buffer=${activeBuffer}
						server=${activeServer}

M components/composer.js => components/composer.js +28 -5
@@ 58,12 58,35 @@ export default class Composer extends Component {
	}

	handleWindowKeyDown(event) {
		if (document.activeElement === document.body && event.key === "/" && !this.state.text) {
			event.preventDefault();
			this.setState({ text: "/" }, () => {
				this.focus();
			});
		// If an <input> or <button> is focused, ignore.
		if (document.activeElement !== document.body && document.activeElement.tagName !== "SECTION") {
			return;
		}

		// 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() {