diff --git a/res/css/views/context_menus/_MessageContextMenu.scss b/res/css/views/context_menus/_MessageContextMenu.scss index 751a85f50c7..27f3966db2b 100644 --- a/res/css/views/context_menus/_MessageContextMenu.scss +++ b/res/css/views/context_menus/_MessageContextMenu.scss @@ -107,6 +107,10 @@ limitations under the License. mask-image: url('$(res)/img/element-icons/room/message-bar/reply.svg'); } + .mx_MessageContextMenu_iconReplyInThread::before { + mask-image: url('$(res)/img/element-icons/message/thread.svg'); + } + .mx_MessageContextMenu_iconReact::before { mask-image: url('$(res)/img/element-icons/room/message-bar/emoji.svg'); } diff --git a/src/components/views/context_menus/MessageContextMenu.tsx b/src/components/views/context_menus/MessageContextMenu.tsx index 11e173975dd..0bc343e1c48 100644 --- a/src/components/views/context_menus/MessageContextMenu.tsx +++ b/src/components/views/context_menus/MessageContextMenu.tsx @@ -22,6 +22,7 @@ import { EventType, RelationType } from "matrix-js-sdk/src/@types/event"; import { Relations } from 'matrix-js-sdk/src/models/relations'; import { RoomMemberEvent } from "matrix-js-sdk/src/models/room-member"; import { M_POLL_START } from "matrix-events-sdk"; +import { Thread } from "matrix-js-sdk/src/models/thread"; import { MatrixClientPeg } from '../../../MatrixClientPeg'; import dis from '../../../dispatcher/dispatcher'; @@ -58,6 +59,9 @@ import { OpenReportEventDialogPayload } from "../../../dispatcher/payloads/OpenR import { createMapSiteLinkFromEvent } from '../../../utils/location'; import { getForwardableEvent } from '../../../events/forward/getForwardableEvent'; import { getShareableLocationEvent } from '../../../events/location/getShareableLocationEvent'; +import { showThread } from "../../../dispatcher/dispatch-actions/threads"; +import RightPanel from "../../structures/RightPanel"; +import RightPanelStore from "../../../stores/right-panel/RightPanelStore"; interface IProps extends IPosition { chevronFace: ChevronFace; @@ -281,6 +285,30 @@ export default class MessageContextMenu extends React.Component this.closeMenu(); }; + private onReplyInThreadClick = (): void => { + const { mxEvent } = this.props; + + if (!localStorage.getItem("mx_seen_feature_thread")) { + localStorage.setItem("mx_seen_feature_thread", "true"); + } + + if (mxEvent.getThread() && !mxEvent.isThreadRoot) { + showThread({ + rootEvent: mxEvent.getThread().rootEvent, + initialEvent: mxEvent, + scroll_into_view: true, + highlighted: true, + push: RightPanelStore.instance.isOpen, + }); + } else { + showThread({ + rootEvent: mxEvent, + push: RightPanelStore.instance.isOpen, + }); + } + this.closeMenu(); + }; + private onReactClick = (): void => { this.setState({ reactionPickerDisplayed: true }); }; @@ -582,6 +610,22 @@ export default class MessageContextMenu extends React.Component ); } + let replyInThreadButton: JSX.Element; + if ( + rightClick && + contentActionable && + canSendMessages && SettingsStore.getValue("feature_thread") && + Thread.hasServerSideSupport + ) { + replyInThreadButton = ( + + ); + } + let reactButton; if (rightClick && contentActionable && canReact) { reactButton = ( @@ -621,6 +665,7 @@ export default class MessageContextMenu extends React.Component { reactButton } { replyButton } + { replyInThreadButton } { editButton } );