From df6de7daf5b700532cb2a5e7609a74f3b8ae660d Mon Sep 17 00:00:00 2001 From: KMY Date: Fri, 24 Feb 2023 17:51:57 +0900 Subject: [PATCH] Add emoji reaction bar into status view --- .../mastodon/actions/importer/normalizer.js | 4 + app/javascript/mastodon/components/status.jsx | 9 +++ .../components/status_emoji_reactions_bar.jsx | 74 +++++++++++++++++++ .../status/components/detailed_status.jsx | 9 +++ .../styles/mastodon/components.scss | 33 +++++++++ 5 files changed, 129 insertions(+) create mode 100644 app/javascript/mastodon/components/status_emoji_reactions_bar.jsx diff --git a/app/javascript/mastodon/actions/importer/normalizer.js b/app/javascript/mastodon/actions/importer/normalizer.js index 8a22f83fa4..6767b5a830 100644 --- a/app/javascript/mastodon/actions/importer/normalizer.js +++ b/app/javascript/mastodon/actions/importer/normalizer.js @@ -66,6 +66,10 @@ export function normalizeStatus(status, normalOldStatus) { normalStatus.filtered = status.filtered.map(normalizeFilterResult); } + if (status.emoji_reactions) { + normalStatus.emojiReactions = status.emoji_reactions; + } + // Only calculate these values when status first encountered and // when the underlying values change. Otherwise keep the ones // already in the reducer diff --git a/app/javascript/mastodon/components/status.jsx b/app/javascript/mastodon/components/status.jsx index 2e2d966345..28b1cf321d 100644 --- a/app/javascript/mastodon/components/status.jsx +++ b/app/javascript/mastodon/components/status.jsx @@ -7,6 +7,7 @@ import RelativeTimestamp from './relative_timestamp'; import DisplayName from './display_name'; import StatusContent from './status_content'; import StatusActionBar from './status_action_bar'; +import StatusEmojiReactionsBar from './status_emoji_reactions_bar'; import AttachmentList from './attachment_list'; import Card from '../features/status/components/card'; import { injectIntl, defineMessages, FormattedMessage } from 'react-intl'; @@ -505,6 +506,12 @@ class Status extends ImmutablePureComponent { const visibilityIcon = visibilityIconInfo[status.get('visibility')]; + let emojiReactionsBar = null; + if (status.get('emoji_reactions')) { + const emojiReactions = status.get('emoji_reactions'); + emojiReactionsBar = ; + } + return (
@@ -538,6 +545,8 @@ class Status extends ImmutablePureComponent { {media} + {emojiReactionsBar} +
diff --git a/app/javascript/mastodon/components/status_emoji_reactions_bar.jsx b/app/javascript/mastodon/components/status_emoji_reactions_bar.jsx new file mode 100644 index 0000000000..9761fcca39 --- /dev/null +++ b/app/javascript/mastodon/components/status_emoji_reactions_bar.jsx @@ -0,0 +1,74 @@ +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import PropTypes from 'prop-types'; +import { FormattedMessage, injectIntl } from 'react-intl'; +import emojify from '../features/emoji/emoji'; +import classNames from 'classnames'; + +class EmojiReactionButton extends React.PureComponent { + + static propTypes = { + name: ImmutablePropTypes.map, + url: PropTypes.string, + staticUrl: PropTypes.string, + count: PropTypes.number.isRequired, + me: PropTypes.bool, + onClick: PropTypes.func, + }; + + render () { + const { name, url, staticUrl, count, me } = this.props; + + let emojiHtml = null; + if (url) { + let customEmojis = {}; + customEmojis[name] = { url, static_url: staticUrl }; + emojiHtml = emojify(`:${name}:`, customEmojis); + } else { + emojiHtml = emojify(name); + } + + const classList = { + 'emoji-reactions-bar__button': true, + 'toggled': me, + }; + + return ( + + ); + } + +} + +export default @injectIntl +class StatusEmojiReactionsBar extends React.PureComponent { + + static propTypes = { + emojiReactions: ImmutablePropTypes.map.isRequired, + statusId: PropTypes.string, + }; + + render () { + const { emojiReactions, statusId } = this.props; + + const emojiButtons = React.Children.map(emojiReactions, (emoji) => ( + )); + + return ( +
+ {emojiButtons} +
+ ); + } + +} diff --git a/app/javascript/mastodon/features/status/components/detailed_status.jsx b/app/javascript/mastodon/features/status/components/detailed_status.jsx index 064231ffe3..fa67905ba0 100644 --- a/app/javascript/mastodon/features/status/components/detailed_status.jsx +++ b/app/javascript/mastodon/features/status/components/detailed_status.jsx @@ -4,6 +4,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import Avatar from '../../../components/avatar'; import DisplayName from '../../../components/display_name'; import StatusContent from '../../../components/status_content'; +import StatusEmojiReactionsBar from '../../../components/status_emoji_reactions_bar'; import MediaGallery from '../../../components/media_gallery'; import { Link } from 'react-router-dom'; import { injectIntl, defineMessages, FormattedDate } from 'react-intl'; @@ -187,6 +188,12 @@ class DetailedStatus extends ImmutablePureComponent { media = ; } + let emojiReactionsBar = null; + if (status.get('emoji_reactions')) { + const emojiReactions = status.get('emoji_reactions'); + emojiReactionsBar = ; + } + if (status.get('application')) { applicationLink = ยท {status.getIn(['application', 'name'])}; } @@ -275,6 +282,8 @@ class DetailedStatus extends ImmutablePureComponent { {media} + {emojiReactionsBar} +
diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 49a5bda34f..7a1198c098 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -1262,6 +1262,39 @@ body > [data-popper-placement] { } } +.status__emoji-reactions-bar { + display: flex; + gap: 8px; + margin: 8px 0 2px 4px; + + .emoji-reactions-bar__button { + background: lighten($ui-base-color, 16%); + border: 0; + cursor: pointer; + display: flex; + justify-items: center; + align-items: center; + height: 20px; + + &.toggled { + background: darken($ui-primary-color, 16%); + } + + .emoji { + display: block; + height: 16px; + img { + margin-top: 0; + margin-bottom: 0; + } + } + .count { + display: block; + margin: 0 2px; + } + } +} + .status__action-bar { display: flex; justify-content: space-between;