From cdd909f2dd6c8c5a3ac5c7a8aade80fd7a80516a Mon Sep 17 00:00:00 2001 From: ginnyTheCat Date: Tue, 8 Feb 2022 12:43:59 +0100 Subject: [PATCH] Keyboard focus related bugs (#299) * Focus when opening the emoji board and editing a message * Clean emoji board after closing * Focus room search and member search * Resolve conversations --- src/app/atoms/input/Input.jsx | 7 ++++++- src/app/molecules/message/Message.jsx | 13 +++++++++++-- src/app/molecules/room-members/RoomMembers.jsx | 11 +++++++++-- src/app/molecules/room-search/RoomSearch.jsx | 3 ++- src/app/organisms/emoji-board/EmojiBoard.jsx | 15 +++++++++++---- .../organisms/emoji-board/EmojiBoardOpener.jsx | 8 ++++++-- 6 files changed, 45 insertions(+), 12 deletions(-) diff --git a/src/app/atoms/input/Input.jsx b/src/app/atoms/input/Input.jsx index b65d521..d9f79eb 100644 --- a/src/app/atoms/input/Input.jsx +++ b/src/app/atoms/input/Input.jsx @@ -8,7 +8,7 @@ function Input({ id, label, name, value, placeholder, required, type, onChange, forwardRef, resizable, minHeight, onResize, state, - onKeyDown, disabled, + onKeyDown, disabled, autoFocus, }) { return (
@@ -30,6 +30,7 @@ function Input({ onResize={onResize} onKeyDown={onKeyDown} disabled={disabled} + autoFocus={autoFocus} /> ) : ( )}
@@ -67,6 +70,7 @@ Input.defaultProps = { state: 'normal', onKeyDown: null, disabled: false, + autoFocus: false, }; Input.propTypes = { @@ -85,6 +89,7 @@ Input.propTypes = { state: PropTypes.oneOf(['normal', 'success', 'error']), onKeyDown: PropTypes.func, disabled: PropTypes.bool, + autoFocus: PropTypes.bool, }; export default Input; diff --git a/src/app/molecules/message/Message.jsx b/src/app/molecules/message/Message.jsx index 488ad4b..16850f2 100644 --- a/src/app/molecules/message/Message.jsx +++ b/src/app/molecules/message/Message.jsx @@ -1,5 +1,7 @@ /* eslint-disable react/prop-types */ -import React, { useState, useEffect, useCallback, useRef } from 'react'; +import React, { + useState, useEffect, useCallback, useRef, +} from 'react'; import PropTypes from 'prop-types'; import './Message.scss'; @@ -245,6 +247,14 @@ MessageBody.propTypes = { function MessageEdit({ body, onSave, onCancel }) { const editInputRef = useRef(null); + useEffect(() => { + editInputRef.current.focus(); + + // Setting the value here instead of using the value prop below + // makes the cursor end up at the end of the line instead of the begining + editInputRef.current.value = body; + }, []); + const handleKeyDown = (e) => { if (e.keyCode === 13 && e.shiftKey === false) { e.preventDefault(); @@ -257,7 +267,6 @@ function MessageEdit({ body, onSave, onCancel }) { Search member - +
{`${searchMembers ? `Found — ${mList.length}` : members.length} members`}
diff --git a/src/app/organisms/emoji-board/EmojiBoard.jsx b/src/app/organisms/emoji-board/EmojiBoard.jsx index c41d8f9..1e61abd 100644 --- a/src/app/organisms/emoji-board/EmojiBoard.jsx +++ b/src/app/organisms/emoji-board/EmojiBoard.jsx @@ -128,8 +128,7 @@ function SearchedEmoji() { return ; } -function EmojiBoard({ onSelect }) { - const searchRef = useRef(null); +function EmojiBoard({ onSelect, searchRef }) { const scrollEmojisRef = useRef(null); const emojiInfo = useRef(null); @@ -182,8 +181,8 @@ function EmojiBoard({ onSelect }) { setEmojiInfo({ shortcode: shortcodes[0], src, unicode }); } - function handleSearchChange(e) { - const term = e.target.value; + function handleSearchChange() { + const term = searchRef.current.value; asyncSearch.search(term); scrollEmojisRef.current.scrollTop = 0; } @@ -213,9 +212,16 @@ function EmojiBoard({ onSelect }) { setAvailableEmojis(packs); }; + const onOpen = () => { + searchRef.current.value = ''; + handleSearchChange(); + }; + navigation.on(cons.events.navigation.ROOM_SELECTED, updateAvailableEmoji); + navigation.on(cons.events.navigation.EMOJIBOARD_OPENED, onOpen); return () => { navigation.removeListener(cons.events.navigation.ROOM_SELECTED, updateAvailableEmoji); + navigation.removeListener(cons.events.navigation.EMOJIBOARD_OPENED, onOpen); }; }, []); @@ -312,6 +318,7 @@ function EmojiBoard({ onSelect }) { EmojiBoard.propTypes = { onSelect: PropTypes.func.isRequired, + searchRef: PropTypes.shape({}).isRequired, }; export default EmojiBoard; diff --git a/src/app/organisms/emoji-board/EmojiBoardOpener.jsx b/src/app/organisms/emoji-board/EmojiBoardOpener.jsx index b16a9e3..32b7a83 100644 --- a/src/app/organisms/emoji-board/EmojiBoardOpener.jsx +++ b/src/app/organisms/emoji-board/EmojiBoardOpener.jsx @@ -2,6 +2,7 @@ import React, { useEffect, useRef } from 'react'; import cons from '../../../client/state/cons'; import navigation from '../../../client/state/navigation'; +import settings from '../../../client/state/settings'; import ContextMenu from '../../atoms/context-menu/ContextMenu'; import EmojiBoard from './EmojiBoard'; @@ -10,6 +11,7 @@ let requestCallback = null; let isEmojiBoardVisible = false; function EmojiBoardOpener() { const openerRef = useRef(null); + const searchRef = useRef(null); function openEmojiBoard(cords, requestEmojiCallback) { if (requestCallback !== null || isEmojiBoardVisible) { @@ -25,7 +27,9 @@ function EmojiBoardOpener() { function afterEmojiBoardToggle(isVisible) { isEmojiBoardVisible = isVisible; - if (!isVisible) { + if (isVisible) { + if (!settings.isTouchScreenDevice) searchRef.current.focus(); + } else { setTimeout(() => { if (!isEmojiBoardVisible) requestCallback = null; }, 500); @@ -46,7 +50,7 @@ function EmojiBoardOpener() { return ( + )} afterToggle={afterEmojiBoardToggle} render={(toggleMenu) => (