From 471540d9aa2c394c089cbfac0be61b54b0328648 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 | 11 +++ .../components/status_emoji_reactions_bar.jsx | 74 +++++++++++++++++++ .../status/components/detailed_status.jsx | 10 ++- .../styles/mastodon/components.scss | 32 ++++++++ 5 files changed, 130 insertions(+), 1 deletion(-) 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 0b1f024a4..f652f4c92 100644 --- a/app/javascript/mastodon/actions/importer/normalizer.js +++ b/app/javascript/mastodon/actions/importer/normalizer.js @@ -40,6 +40,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 c50f3395b..72ec4b993 100644 --- a/app/javascript/mastodon/components/status.jsx +++ b/app/javascript/mastodon/components/status.jsx @@ -1,5 +1,8 @@ import PropTypes from 'prop-types'; +import StatusEmojiReactionsBar from './status_emoji_reactions_bar'; +import AttachmentList from './attachment_list'; + import { injectIntl, defineMessages, FormattedMessage } from 'react-intl'; import classNames from 'classnames'; @@ -669,6 +672,12 @@ class Status extends ImmutablePureComponent { const {statusContentProps, hashtagBar} = getHashtagBarForStatus(status); const expanded = !status.get('hidden') || status.get('spoiler_text').length === 0; + let emojiReactionsBar = null; + if (status.get('emoji_reactions')) { + const emojiReactions = status.get('emoji_reactions'); + emojiReactionsBar = ; + } + return (
@@ -712,6 +721,8 @@ class Status extends ImmutablePureComponent { {expanded && hashtagBar} + {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 000000000..d00833992 --- /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 { 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 ( + + ); + } + +} + +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} +
+ ); + } + +} +export default injectIntl(StatusEmojiReactionsBar); \ No newline at end of file diff --git a/app/javascript/mastodon/features/status/components/detailed_status.jsx b/app/javascript/mastodon/features/status/components/detailed_status.jsx index c81d83d71..9e4ac8980 100644 --- a/app/javascript/mastodon/features/status/components/detailed_status.jsx +++ b/app/javascript/mastodon/features/status/components/detailed_status.jsx @@ -6,6 +6,7 @@ import classNames from 'classnames'; import { Link, withRouter } from 'react-router-dom'; import ImmutablePropTypes from 'react-immutable-proptypes'; +import StatusEmojiReactionsBar from '../../../components/status_emoji_reactions_bar'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { ReactComponent as AlternateEmailIcon } from '@material-symbols/svg-600/outlined/alternate_email.svg'; @@ -254,9 +255,14 @@ class DetailedStatus extends ImmutablePureComponent { } else if (status.get('spoiler_text').length === 0) { return ; } - } + let emojiReactionsBar = null; + if (status.get('emoji_reactions')) { + const emojiReactions = status.get('emoji_reactions'); + emojiReactionsBar = ; + } + if (status.get('application')) { applicationLink = <> ยท {status.getIn(['application', 'name'])}; } @@ -351,6 +357,8 @@ class DetailedStatus extends ImmutablePureComponent { {expanded && hashtagBar} + {emojiReactionsBar} +
diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index db1d79a07..22df47cec 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -1417,6 +1417,38 @@ body > [data-popper-placement] { color: $highlight-text-color; } } +.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;