diff --git a/res/css/views/messages/_ReactionsRow.scss b/res/css/views/messages/_ReactionsRow.scss index f1c19f45a9..244439bf74 100644 --- a/res/css/views/messages/_ReactionsRow.scss +++ b/res/css/views/messages/_ReactionsRow.scss @@ -62,7 +62,7 @@ limitations under the License. vertical-align: middle; &:link, &:visited { - color: $tertiary-fg-color + color: $tertiary-fg-color; } &:hover { diff --git a/src/components/views/messages/ReactionsRow.js b/src/components/views/messages/ReactionsRow.tsx similarity index 82% rename from src/components/views/messages/ReactionsRow.js rename to src/components/views/messages/ReactionsRow.tsx index a7997c0e32..e1fcbe5364 100644 --- a/src/components/views/messages/ReactionsRow.js +++ b/src/components/views/messages/ReactionsRow.tsx @@ -1,5 +1,5 @@ /* -Copyright 2019 New Vector Ltd +Copyright 2019, 2021 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,29 +14,30 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React from 'react'; -import PropTypes from 'prop-types'; -import { EventType } from "matrix-js-sdk/src/@types/event"; +import React from "react"; import classNames from "classnames"; +import { EventType } from "matrix-js-sdk/src/@types/event"; +import { MatrixEvent } from "matrix-js-sdk/src/models/event"; +import { Relations } from "matrix-js-sdk/src/models/relations"; -import * as sdk from '../../../index'; import { _t } from '../../../languageHandler'; import { isContentActionable } from '../../../utils/EventUtils'; -import {MatrixClientPeg} from '../../../MatrixClientPeg'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; -import {ContextMenuTooltipButton} from "../../../accessibility/context_menu/ContextMenuTooltipButton"; -import {aboveLeftOf, ContextMenu, useContextMenu} from "../../structures/ContextMenu"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; +import { ContextMenuTooltipButton } from "../../../accessibility/context_menu/ContextMenuTooltipButton"; +import { aboveLeftOf, ContextMenu, useContextMenu } from "../../structures/ContextMenu"; +import ReactionPicker from "../emojipicker/ReactionPicker"; +import ReactionsRowButton from "./ReactionsRowButton"; +import MatrixClientContext from "../../../contexts/MatrixClientContext"; // The maximum number of reactions to initially show on a message. const MAX_ITEMS_WHEN_LIMITED = 8; -const ReactButton = ({ mxEvent, reactions }) => { +const ReactButton = ({ mxEvent, reactions }: IProps) => { const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu(); let contextMenu; if (menuDisplayed) { const buttonRect = button.current.getBoundingClientRect(); - const ReactionPicker = sdk.getComponent('emojipicker.ReactionPicker'); contextMenu = ; @@ -57,17 +58,24 @@ const ReactButton = ({ mxEvent, reactions }) => { ; }; -@replaceableComponent("views.messages.ReactionsRow") -export default class ReactionsRow extends React.PureComponent { - static propTypes = { - // The event we're displaying reactions for - mxEvent: PropTypes.object.isRequired, - // The Relations model from the JS SDK for reactions to `mxEvent` - reactions: PropTypes.object, - } +interface IProps { + // The event we're displaying reactions for + mxEvent: MatrixEvent; + // The Relations model from the JS SDK for reactions to `mxEvent` + reactions?: Relations; +} - constructor(props) { - super(props); +interface IState { + myReactions: MatrixEvent[]; + showAll: boolean; +} + +@replaceableComponent("views.messages.ReactionsRow") +export default class ReactionsRow extends React.PureComponent { + static contextType = MatrixClientContext; + + constructor(props, context) { + super(props, context); if (props.reactions) { props.reactions.on("Relations.add", this.onReactionsChange); @@ -123,7 +131,7 @@ export default class ReactionsRow extends React.PureComponent { if (!reactions) { return null; } - const userId = MatrixClientPeg.get().getUserId(); + const userId = this.context.getUserId(); const myReactions = reactions.getAnnotationsBySender()[userId]; if (!myReactions) { return null; @@ -145,7 +153,6 @@ export default class ReactionsRow extends React.PureComponent { return null; } - const ReactionsRowButton = sdk.getComponent('messages.ReactionsRowButton'); let items = reactions.getSortedAnnotationsByKey().map(([content, events]) => { const count = events.size; if (!count) { @@ -182,7 +189,7 @@ export default class ReactionsRow extends React.PureComponent { ; } - const cli = MatrixClientPeg.get(); + const cli = this.context; let addReactionButton; if (cli.getRoom(mxEvent.getRoomId()).currentState.maySendEvent(EventType.Reaction, cli.getUserId())) { diff --git a/src/components/views/messages/ReactionsRowButton.js b/src/components/views/messages/ReactionsRowButton.tsx similarity index 73% rename from src/components/views/messages/ReactionsRowButton.js rename to src/components/views/messages/ReactionsRowButton.tsx index b37a949e57..393c6bca88 100644 --- a/src/components/views/messages/ReactionsRowButton.js +++ b/src/components/views/messages/ReactionsRowButton.tsx @@ -1,5 +1,5 @@ /* -Copyright 2019 New Vector Ltd +Copyright 2019, 2021 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,49 +14,54 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React from 'react'; -import PropTypes from 'prop-types'; -import classNames from 'classnames'; +import React from "react"; +import classNames from "classnames"; +import { MatrixEvent } from "matrix-js-sdk/src/models/event"; -import {MatrixClientPeg} from '../../../MatrixClientPeg'; -import * as sdk from '../../../index'; import { _t } from '../../../languageHandler'; import { formatCommaSeparatedList } from '../../../utils/FormattingUtils'; import dis from "../../../dispatcher/dispatcher"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; +import ReactionsRowButtonTooltip from "./ReactionsRowButtonTooltip"; +import AccessibleButton from "../elements/AccessibleButton"; +import MatrixClientContext from "../../../contexts/MatrixClientContext"; + +interface IProps { + // The event we're displaying reactions for + mxEvent: MatrixEvent; + // The reaction content / key / emoji + content: string; + // The count of votes for this key + count: number; + // A Set of Martix reaction events for this key + reactionEvents: Set; + // A possible Matrix event if the current user has voted for this type + myReactionEvent?: MatrixEvent; +} + +interface IState { + tooltipRendered: boolean; + tooltipVisible: boolean; +} @replaceableComponent("views.messages.ReactionsRowButton") -export default class ReactionsRowButton extends React.PureComponent { - static propTypes = { - // The event we're displaying reactions for - mxEvent: PropTypes.object.isRequired, - // The reaction content / key / emoji - content: PropTypes.string.isRequired, - // The count of votes for this key - count: PropTypes.number.isRequired, - // A Set of Martix reaction events for this key - reactionEvents: PropTypes.object.isRequired, - // A possible Matrix event if the current user has voted for this type - myReactionEvent: PropTypes.object, - } +export default class ReactionsRowButton extends React.PureComponent { + static contextType = MatrixClientContext; - constructor(props) { - super(props); + state = { + tooltipRendered: false, + tooltipVisible: false, + }; - this.state = { - tooltipVisible: false, - }; - } - - onClick = (ev) => { + onClick = () => { const { mxEvent, myReactionEvent, content } = this.props; if (myReactionEvent) { - MatrixClientPeg.get().redactEvent( + this.context.redactEvent( mxEvent.getRoomId(), myReactionEvent.getId(), ); } else { - MatrixClientPeg.get().sendEvent(mxEvent.getRoomId(), "m.reaction", { + this.context.sendEvent(mxEvent.getRoomId(), "m.reaction", { "m.relates_to": { "rel_type": "m.annotation", "event_id": mxEvent.getId(), @@ -83,8 +88,6 @@ export default class ReactionsRowButton extends React.PureComponent { } render() { - const ReactionsRowButtonTooltip = - sdk.getComponent('messages.ReactionsRowButtonTooltip'); const { mxEvent, content, count, reactionEvents, myReactionEvent } = this.props; const classes = classNames({ @@ -102,7 +105,7 @@ export default class ReactionsRowButton extends React.PureComponent { />; } - const room = MatrixClientPeg.get().getRoom(mxEvent.getRoomId()); + const room = this.context.getRoom(mxEvent.getRoomId()); let label; if (room) { const senders = []; @@ -130,7 +133,6 @@ export default class ReactionsRowButton extends React.PureComponent { ); } const isPeeking = room.getMyMembership() !== "join"; - const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); return ; + visible: boolean; +} @replaceableComponent("views.messages.ReactionsRowButtonTooltip") -export default class ReactionsRowButtonTooltip extends React.PureComponent { - static propTypes = { - // The event we're displaying reactions for - mxEvent: PropTypes.object.isRequired, - // The reaction content / key / emoji - content: PropTypes.string.isRequired, - // A Set of Martix reaction events for this key - reactionEvents: PropTypes.object.isRequired, - visible: PropTypes.bool.isRequired, - } +export default class ReactionsRowButtonTooltip extends React.PureComponent { + static contextType = MatrixClientContext; render() { - const Tooltip = sdk.getComponent('elements.Tooltip'); const { content, reactionEvents, mxEvent, visible } = this.props; - const room = MatrixClientPeg.get().getRoom(mxEvent.getRoomId()); + const room = this.context.getRoom(mxEvent.getRoomId()); let tooltipLabel; if (room) { const senders = [];