Autofocus correct composer after sending reaction (#7950)

This commit is contained in:
Michael Telatynski 2022-03-02 16:31:34 +00:00 committed by GitHub
parent 61cd463a3b
commit c727942095
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 39 additions and 23 deletions

View file

@ -107,6 +107,7 @@ import { JoinRoomPayload } from "../../dispatcher/payloads/JoinRoomPayload";
import { DoAfterSyncPreparedPayload } from '../../dispatcher/payloads/DoAfterSyncPreparedPayload'; import { DoAfterSyncPreparedPayload } from '../../dispatcher/payloads/DoAfterSyncPreparedPayload';
import FileDropTarget from './FileDropTarget'; import FileDropTarget from './FileDropTarget';
import Measured from '../views/elements/Measured'; import Measured from '../views/elements/Measured';
import { FocusComposerPayload } from '../../dispatcher/payloads/FocusComposerPayload';
const DEBUG = false; const DEBUG = false;
let debuglog = function(msg: string) {}; let debuglog = function(msg: string) {};
@ -918,8 +919,11 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
} }
case Action.FocusAComposer: { case Action.FocusAComposer: {
// re-dispatch to the correct composer dis.dispatch<FocusComposerPayload>({
dis.fire(this.state.editState ? Action.FocusEditMessageComposer : Action.FocusSendMessageComposer); ...(payload as FocusComposerPayload),
// re-dispatch to the correct composer
action: this.state.editState ? Action.FocusEditMessageComposer : Action.FocusSendMessageComposer,
});
break; break;
} }

View file

@ -17,16 +17,20 @@ limitations under the License.
import React from 'react'; import React from 'react';
import { MatrixEvent } from "matrix-js-sdk/src/models/event"; import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { Relations, RelationsEvent } from 'matrix-js-sdk/src/models/relations';
import { EventType, RelationType } from 'matrix-js-sdk/src/@types/event';
import EmojiPicker from "./EmojiPicker"; import EmojiPicker from "./EmojiPicker";
import { MatrixClientPeg } from "../../../MatrixClientPeg"; import { MatrixClientPeg } from "../../../MatrixClientPeg";
import dis from "../../../dispatcher/dispatcher"; import dis from "../../../dispatcher/dispatcher";
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
import { Action } from '../../../dispatcher/actions'; import { Action } from '../../../dispatcher/actions';
import RoomContext from "../../../contexts/RoomContext";
import { FocusComposerPayload } from '../../../dispatcher/payloads/FocusComposerPayload';
interface IProps { interface IProps {
mxEvent: MatrixEvent; mxEvent: MatrixEvent;
reactions: any; // TODO type this once js-sdk is more typescripted reactions?: Relations;
onFinished(): void; onFinished(): void;
} }
@ -36,8 +40,11 @@ interface IState {
@replaceableComponent("views.emojipicker.ReactionPicker") @replaceableComponent("views.emojipicker.ReactionPicker")
class ReactionPicker extends React.Component<IProps, IState> { class ReactionPicker extends React.Component<IProps, IState> {
constructor(props) { static contextType = RoomContext;
super(props); public context!: React.ContextType<typeof RoomContext>;
constructor(props: IProps, context: React.ContextType<typeof RoomContext>) {
super(props, context);
this.state = { this.state = {
selectedEmojis: new Set(Object.keys(this.getReactions())), selectedEmojis: new Set(Object.keys(this.getReactions())),
@ -54,17 +61,17 @@ class ReactionPicker extends React.Component<IProps, IState> {
private addListeners() { private addListeners() {
if (this.props.reactions) { if (this.props.reactions) {
this.props.reactions.on("Relations.add", this.onReactionsChange); this.props.reactions.on(RelationsEvent.Add, this.onReactionsChange);
this.props.reactions.on("Relations.remove", this.onReactionsChange); this.props.reactions.on(RelationsEvent.Remove, this.onReactionsChange);
this.props.reactions.on("Relations.redaction", this.onReactionsChange); this.props.reactions.on(RelationsEvent.Redaction, this.onReactionsChange);
} }
} }
componentWillUnmount() { componentWillUnmount() {
if (this.props.reactions) { if (this.props.reactions) {
this.props.reactions.removeListener("Relations.add", this.onReactionsChange); this.props.reactions.removeListener(RelationsEvent.Add, this.onReactionsChange);
this.props.reactions.removeListener("Relations.remove", this.onReactionsChange); this.props.reactions.removeListener(RelationsEvent.Remove, this.onReactionsChange);
this.props.reactions.removeListener("Relations.redaction", this.onReactionsChange); this.props.reactions.removeListener(RelationsEvent.Redaction, this.onReactionsChange);
} }
} }
@ -85,28 +92,31 @@ class ReactionPicker extends React.Component<IProps, IState> {
}); });
}; };
onChoose = (reaction: string) => { private onChoose = (reaction: string) => {
this.componentWillUnmount(); this.componentWillUnmount();
this.props.onFinished(); this.props.onFinished();
const myReactions = this.getReactions(); const myReactions = this.getReactions();
if (myReactions.hasOwnProperty(reaction)) { if (myReactions.hasOwnProperty(reaction)) {
MatrixClientPeg.get().redactEvent( MatrixClientPeg.get().redactEvent(this.props.mxEvent.getRoomId(), myReactions[reaction]);
this.props.mxEvent.getRoomId(), dis.dispatch<FocusComposerPayload>({
myReactions[reaction], action: Action.FocusAComposer,
); context: this.context.timelineRenderingType,
dis.fire(Action.FocusAComposer); });
// Tell the emoji picker not to bump this in the more frequently used list. // Tell the emoji picker not to bump this in the more frequently used list.
return false; return false;
} else { } else {
MatrixClientPeg.get().sendEvent(this.props.mxEvent.getRoomId(), "m.reaction", { MatrixClientPeg.get().sendEvent(this.props.mxEvent.getRoomId(), EventType.Reaction, {
"m.relates_to": { "m.relates_to": {
"rel_type": "m.annotation", "rel_type": RelationType.Annotation,
"event_id": this.props.mxEvent.getId(), "event_id": this.props.mxEvent.getId(),
"key": reaction, "key": reaction,
}, },
}); });
dis.dispatch({ action: "message_sent" }); dis.dispatch({ action: "message_sent" });
dis.fire(Action.FocusAComposer); dis.dispatch<FocusComposerPayload>({
action: Action.FocusAComposer,
context: this.context.timelineRenderingType,
});
return true; return true;
} }
}; };

View file

@ -77,8 +77,7 @@ export enum Action {
/** /**
* Focuses the user's cursor to the edit message composer or send message * Focuses the user's cursor to the edit message composer or send message
* composer based on the current edit state. No additional payload * composer based on the current edit state. Should be used with a FocusComposerPayload.
* information required.
*/ */
FocusAComposer = "focus_a_composer", FocusAComposer = "focus_a_composer",

View file

@ -19,7 +19,10 @@ import { Action } from "../actions";
import { TimelineRenderingType } from "../../contexts/RoomContext"; import { TimelineRenderingType } from "../../contexts/RoomContext";
export interface FocusComposerPayload extends ActionPayload { export interface FocusComposerPayload extends ActionPayload {
action: Action.FocusEditMessageComposer | Action.FocusSendMessageComposer | "reply_to_event"; action: Action.FocusAComposer
| Action.FocusEditMessageComposer
| Action.FocusSendMessageComposer
| "reply_to_event";
context?: TimelineRenderingType; // defaults to Room type for backwards compatibility context?: TimelineRenderingType; // defaults to Room type for backwards compatibility
} }