diff --git a/src/ContentMessages.tsx b/src/ContentMessages.tsx index 670c175a48..0ab193081b 100644 --- a/src/ContentMessages.tsx +++ b/src/ContentMessages.tsx @@ -569,7 +569,7 @@ export default class ContentMessages { dis.dispatch({ action: Action.UploadStarted, upload }); // Focus the composer view - dis.fire(Action.FocusComposer); + dis.fire(Action.FocusSendMessageComposer); function onProgress(ev) { upload.total = ev.total; diff --git a/src/components/structures/LoggedInView.tsx b/src/components/structures/LoggedInView.tsx index 5a26967cb0..89fa8db376 100644 --- a/src/components/structures/LoggedInView.tsx +++ b/src/components/structures/LoggedInView.tsx @@ -398,7 +398,7 @@ class LoggedInView extends React.Component { // refocusing during a paste event will make the // paste end up in the newly focused element, // so dispatch synchronously before paste happens - dis.fire(Action.FocusComposer, true); + dis.fire(Action.FocusSendMessageComposer, true); } }; @@ -552,7 +552,7 @@ class LoggedInView extends React.Component { if (!isClickShortcut && ev.key !== Key.TAB && !canElementReceiveInput(ev.target)) { // synchronous dispatch so we focus before key generates input - dis.fire(Action.FocusComposer, true); + dis.fire(Action.FocusSendMessageComposer, true); ev.stopPropagation(); // we should *not* preventDefault() here as // that would prevent typing in the now-focussed composer diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index c7a200239c..d692b0fa7f 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -443,7 +443,7 @@ export default class MatrixChat extends React.PureComponent { CountlyAnalytics.instance.trackPageChange(durationMs); } if (this.focusComposer) { - dis.fire(Action.FocusComposer); + dis.fire(Action.FocusSendMessageComposer); this.focusComposer = false; } } @@ -1427,7 +1427,7 @@ export default class MatrixChat extends React.PureComponent { showNotificationsToast(false); } - dis.fire(Action.FocusComposer); + dis.fire(Action.FocusSendMessageComposer); this.setState({ ready: true, }); diff --git a/src/components/structures/RoomSearch.tsx b/src/components/structures/RoomSearch.tsx index 9cdd1efe7e..e8080b4f7b 100644 --- a/src/components/structures/RoomSearch.tsx +++ b/src/components/structures/RoomSearch.tsx @@ -131,7 +131,7 @@ export default class RoomSearch extends React.PureComponent { switch (action) { case RoomListAction.ClearSearch: this.clearInput(); - defaultDispatcher.fire(Action.FocusComposer); + defaultDispatcher.fire(Action.FocusSendMessageComposer); break; case RoomListAction.NextRoom: case RoomListAction.PrevRoom: diff --git a/src/components/structures/RoomStatusBar.js b/src/components/structures/RoomStatusBar.js index f6e42a4f9c..80ea26c3f2 100644 --- a/src/components/structures/RoomStatusBar.js +++ b/src/components/structures/RoomStatusBar.js @@ -118,12 +118,12 @@ export default class RoomStatusBar extends React.PureComponent { this.setState({ isResending: false }); }); this.setState({ isResending: true }); - dis.fire(Action.FocusComposer); + dis.fire(Action.FocusSendMessageComposer); }; _onCancelAllClick = () => { Resend.cancelUnsentEvents(this.props.room); - dis.fire(Action.FocusComposer); + dis.fire(Action.FocusSendMessageComposer); }; _onRoomLocalEchoUpdated = (event, room, oldEventId, oldStatus) => { diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx index 0e77c301fd..8e0b8a5f4a 100644 --- a/src/components/structures/RoomView.tsx +++ b/src/components/structures/RoomView.tsx @@ -818,17 +818,16 @@ export default class RoomView extends React.Component { case Action.ComposerInsert: { // re-dispatch to the correct composer - if (this.state.editState) { - dis.dispatch({ - ...payload, - action: "edit_composer_insert", - }); - } else { - dis.dispatch({ - ...payload, - action: "send_composer_insert", - }); - } + dis.dispatch({ + ...payload, + action: this.state.editState ? "edit_composer_insert" : "send_composer_insert", + }); + break; + } + + case Action.FocusAComposer: { + // re-dispatch to the correct composer + dis.fire(this.state.editState ? Action.FocusEditMessageComposer : Action.FocusSendMessageComposer); break; } @@ -1246,7 +1245,7 @@ export default class RoomView extends React.Component { ContentMessages.sharedInstance().sendContentListToRoom( ev.dataTransfer.files, this.state.room.roomId, this.context, ); - dis.fire(Action.FocusComposer); + dis.fire(Action.FocusSendMessageComposer); this.setState({ draggingFile: false, @@ -1548,7 +1547,7 @@ export default class RoomView extends React.Component { } else { // Otherwise we have to jump manually this.messagePanel.jumpToLiveTimeline(); - dis.fire(Action.FocusComposer); + dis.fire(Action.FocusSendMessageComposer); } }; diff --git a/src/components/views/elements/ReplyThread.js b/src/components/views/elements/ReplyThread.js index aea447c9b1..2047de6c58 100644 --- a/src/components/views/elements/ReplyThread.js +++ b/src/components/views/elements/ReplyThread.js @@ -334,7 +334,7 @@ export default class ReplyThread extends React.Component { events, }); - dis.fire(Action.FocusComposer); + dis.fire(Action.FocusSendMessageComposer); } render() { diff --git a/src/components/views/emojipicker/ReactionPicker.tsx b/src/components/views/emojipicker/ReactionPicker.tsx index d8f8b7f2ff..e129b45c9a 100644 --- a/src/components/views/emojipicker/ReactionPicker.tsx +++ b/src/components/views/emojipicker/ReactionPicker.tsx @@ -22,6 +22,7 @@ import EmojiPicker from "./EmojiPicker"; import { MatrixClientPeg } from "../../../MatrixClientPeg"; import dis from "../../../dispatcher/dispatcher"; import { replaceableComponent } from "../../../utils/replaceableComponent"; +import { Action } from '../../../dispatcher/actions'; interface IProps { mxEvent: MatrixEvent; @@ -93,6 +94,7 @@ class ReactionPicker extends React.Component { this.props.mxEvent.getRoomId(), myReactions[reaction], ); + dis.dispatch({ action: Action.FocusAComposer }); // Tell the emoji picker not to bump this in the more frequently used list. return false; } else { @@ -104,6 +106,7 @@ class ReactionPicker extends React.Component { }, }); dis.dispatch({ action: "message_sent" }); + dis.dispatch({ action: Action.FocusAComposer }); return true; } }; diff --git a/src/components/views/rooms/EditMessageComposer.tsx b/src/components/views/rooms/EditMessageComposer.tsx index fea6499dd8..e4b13e2155 100644 --- a/src/components/views/rooms/EditMessageComposer.tsx +++ b/src/components/views/rooms/EditMessageComposer.tsx @@ -181,7 +181,7 @@ export default class EditMessageComposer extends React.Component } else { this.clearStoredEditorState(); dis.dispatch({ action: 'edit_event', event: null }); - dis.fire(Action.FocusComposer); + dis.fire(Action.FocusSendMessageComposer); } event.preventDefault(); break; @@ -200,7 +200,7 @@ export default class EditMessageComposer extends React.Component private cancelEdit = (): void => { this.clearStoredEditorState(); dis.dispatch({ action: "edit_event", event: null }); - dis.fire(Action.FocusComposer); + dis.fire(Action.FocusSendMessageComposer); }; private get shouldSaveStoredEditorState(): boolean { @@ -375,7 +375,7 @@ export default class EditMessageComposer extends React.Component // close the event editing and focus composer dis.dispatch({ action: "edit_event", event: null }); - dis.fire(Action.FocusComposer); + dis.fire(Action.FocusSendMessageComposer); }; private cancelPreviousPendingEdit(): void { @@ -452,6 +452,8 @@ export default class EditMessageComposer extends React.Component } else if (payload.text) { this.editorRef.current?.insertPlaintext(payload.text); } + } else if (payload.action === Action.FocusEditMessageComposer && this.editorRef.current) { + this.editorRef.current.focus(); } }; diff --git a/src/components/views/rooms/SendMessageComposer.tsx b/src/components/views/rooms/SendMessageComposer.tsx index 2c45c1bbf8..0639c20fef 100644 --- a/src/components/views/rooms/SendMessageComposer.tsx +++ b/src/components/views/rooms/SendMessageComposer.tsx @@ -497,7 +497,7 @@ export default class SendMessageComposer extends React.Component { switch (payload.action) { case 'reply_to_event': - case Action.FocusComposer: + case Action.FocusSendMessageComposer: this.editorRef.current?.focus(); break; case "send_composer_insert": diff --git a/src/dispatcher/actions.ts b/src/dispatcher/actions.ts index 6438ecc0f2..a4bfa171cd 100644 --- a/src/dispatcher/actions.ts +++ b/src/dispatcher/actions.ts @@ -56,9 +56,21 @@ export enum Action { CheckUpdates = "check_updates", /** - * Focuses the user's cursor to the composer. No additional payload information required. + * Focuses the user's cursor to the send message composer. No additional payload information required. */ - FocusComposer = "focus_composer", + FocusSendMessageComposer = "focus_send_message_composer", + + /** + * Focuses the user's cursor to the edit message composer. No additional payload information required. + */ + FocusEditMessageComposer = "focus_edit_message_composer", + + /** + * Focuses the user's cursor to the edit message composer or send message + * composer based on the current edit state. No additional payload + * information required. + */ + FocusAComposer = "focus_a_composer", /** * Opens the user menu (previously known as the top left menu). No additional payload information required.