Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Autofocus correct composer after sending reaction (#7950)
Browse files Browse the repository at this point in the history
  • Loading branch information
t3chguy committed Mar 2, 2022
1 parent 61cd463 commit c727942
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 23 deletions.
8 changes: 6 additions & 2 deletions src/components/structures/RoomView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ import { JoinRoomPayload } from "../../dispatcher/payloads/JoinRoomPayload";
import { DoAfterSyncPreparedPayload } from '../../dispatcher/payloads/DoAfterSyncPreparedPayload';
import FileDropTarget from './FileDropTarget';
import Measured from '../views/elements/Measured';
import { FocusComposerPayload } from '../../dispatcher/payloads/FocusComposerPayload';

const DEBUG = false;
let debuglog = function(msg: string) {};
Expand Down Expand Up @@ -918,8 +919,11 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
}

case Action.FocusAComposer: {
// re-dispatch to the correct composer
dis.fire(this.state.editState ? Action.FocusEditMessageComposer : Action.FocusSendMessageComposer);
dis.dispatch<FocusComposerPayload>({
...(payload as FocusComposerPayload),
// re-dispatch to the correct composer
action: this.state.editState ? Action.FocusEditMessageComposer : Action.FocusSendMessageComposer,
});
break;
}

Expand Down
46 changes: 28 additions & 18 deletions src/components/views/emojipicker/ReactionPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,20 @@ limitations under the License.

import React from 'react';
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 { MatrixClientPeg } from "../../../MatrixClientPeg";
import dis from "../../../dispatcher/dispatcher";
import { replaceableComponent } from "../../../utils/replaceableComponent";
import { Action } from '../../../dispatcher/actions';
import RoomContext from "../../../contexts/RoomContext";
import { FocusComposerPayload } from '../../../dispatcher/payloads/FocusComposerPayload';

interface IProps {
mxEvent: MatrixEvent;
reactions: any; // TODO type this once js-sdk is more typescripted
reactions?: Relations;
onFinished(): void;
}

Expand All @@ -36,8 +40,11 @@ interface IState {

@replaceableComponent("views.emojipicker.ReactionPicker")
class ReactionPicker extends React.Component<IProps, IState> {
constructor(props) {
super(props);
static contextType = RoomContext;
public context!: React.ContextType<typeof RoomContext>;

constructor(props: IProps, context: React.ContextType<typeof RoomContext>) {
super(props, context);

this.state = {
selectedEmojis: new Set(Object.keys(this.getReactions())),
Expand All @@ -54,17 +61,17 @@ class ReactionPicker extends React.Component<IProps, IState> {

private addListeners() {
if (this.props.reactions) {
this.props.reactions.on("Relations.add", this.onReactionsChange);
this.props.reactions.on("Relations.remove", this.onReactionsChange);
this.props.reactions.on("Relations.redaction", this.onReactionsChange);
this.props.reactions.on(RelationsEvent.Add, this.onReactionsChange);
this.props.reactions.on(RelationsEvent.Remove, this.onReactionsChange);
this.props.reactions.on(RelationsEvent.Redaction, this.onReactionsChange);
}
}

componentWillUnmount() {
if (this.props.reactions) {
this.props.reactions.removeListener("Relations.add", this.onReactionsChange);
this.props.reactions.removeListener("Relations.remove", this.onReactionsChange);
this.props.reactions.removeListener("Relations.redaction", this.onReactionsChange);
this.props.reactions.removeListener(RelationsEvent.Add, this.onReactionsChange);
this.props.reactions.removeListener(RelationsEvent.Remove, this.onReactionsChange);
this.props.reactions.removeListener(RelationsEvent.Redaction, this.onReactionsChange);
}
}

Expand All @@ -85,28 +92,31 @@ class ReactionPicker extends React.Component<IProps, IState> {
});
};

onChoose = (reaction: string) => {
private onChoose = (reaction: string) => {
this.componentWillUnmount();
this.props.onFinished();
const myReactions = this.getReactions();
if (myReactions.hasOwnProperty(reaction)) {
MatrixClientPeg.get().redactEvent(
this.props.mxEvent.getRoomId(),
myReactions[reaction],
);
dis.fire(Action.FocusAComposer);
MatrixClientPeg.get().redactEvent(this.props.mxEvent.getRoomId(), myReactions[reaction]);
dis.dispatch<FocusComposerPayload>({
action: Action.FocusAComposer,
context: this.context.timelineRenderingType,
});
// Tell the emoji picker not to bump this in the more frequently used list.
return false;
} else {
MatrixClientPeg.get().sendEvent(this.props.mxEvent.getRoomId(), "m.reaction", {
MatrixClientPeg.get().sendEvent(this.props.mxEvent.getRoomId(), EventType.Reaction, {
"m.relates_to": {
"rel_type": "m.annotation",
"rel_type": RelationType.Annotation,
"event_id": this.props.mxEvent.getId(),
"key": reaction,
},
});
dis.dispatch({ action: "message_sent" });
dis.fire(Action.FocusAComposer);
dis.dispatch<FocusComposerPayload>({
action: Action.FocusAComposer,
context: this.context.timelineRenderingType,
});
return true;
}
};
Expand Down
3 changes: 1 addition & 2 deletions src/dispatcher/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,7 @@ export enum Action {

/**
* 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.
* composer based on the current edit state. Should be used with a FocusComposerPayload.
*/
FocusAComposer = "focus_a_composer",

Expand Down
5 changes: 4 additions & 1 deletion src/dispatcher/payloads/FocusComposerPayload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ import { Action } from "../actions";
import { TimelineRenderingType } from "../../contexts/RoomContext";

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
}

0 comments on commit c727942

Please sign in to comment.