diff --git a/res/css/views/messages/_ReactionsRow.scss b/res/css/views/messages/_ReactionsRow.scss index 2f5695e1fb..e86d23dc7c 100644 --- a/res/css/views/messages/_ReactionsRow.scss +++ b/res/css/views/messages/_ReactionsRow.scss @@ -17,6 +17,26 @@ limitations under the License. .mx_ReactionsRow { margin: 6px 0; color: $primary-fg-color; + + .mx_ReactionsRow_addReactionButton { + position: relative; + display: inline-block; + width: 16px; + height: 16px; + vertical-align: sub; + + &::before { + content: ''; + position: absolute; + height: 100%; + width: 100%; + mask-size: cover; + mask-repeat: no-repeat; + mask-position: center; + background-color: $tertiary-fg-color; + mask-image: url('$(res)/img/element-icons/room/message-bar/emoji.svg'); + } + } } .mx_ReactionsRow_showAll { diff --git a/src/components/views/messages/ReactionsRow.js b/src/components/views/messages/ReactionsRow.js index d5c8ea2ac9..22f12709a7 100644 --- a/src/components/views/messages/ReactionsRow.js +++ b/src/components/views/messages/ReactionsRow.js @@ -16,16 +16,44 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; +import { EventType } from "matrix-js-sdk/src/@types/event"; 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"; // The maximum number of reactions to initially show on a message. const MAX_ITEMS_WHEN_LIMITED = 8; +const ReactButton = ({ mxEvent, reactions }) => { + const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu(); + + let contextMenu; + if (menuDisplayed) { + const buttonRect = button.current.getBoundingClientRect(); + const ReactionPicker = sdk.getComponent('emojipicker.ReactionPicker'); + contextMenu = + + ; + } + + return + + + { contextMenu } + ; +}; + @replaceableComponent("views.messages.ReactionsRow") export default class ReactionsRow extends React.PureComponent { static propTypes = { @@ -151,13 +179,21 @@ export default class ReactionsRow extends React.PureComponent { ; } + const cli = MatrixClientPeg.get(); + + let addReactionButton; + if (cli.getRoom(mxEvent.getRoomId()).currentState.maySendEvent(EventType.Reaction, cli.getUserId())) { + addReactionButton = ; + } + return
- {items} - {showAllButton} + { items } + { addReactionButton } + { showAllButton }
; } } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index dbe712c691..b9e52a8356 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1864,6 +1864,7 @@ "You sent a verification request": "You sent a verification request", "Error decrypting video": "Error decrypting video", "Error processing voice message": "Error processing voice message", + "Add reaction": "Add reaction", "Show all": "Show all", "Reactions": "Reactions", " reacted with %(content)s": " reacted with %(content)s",