diff --git a/app/javascript/flavours/glitch/containers/status_container.js b/app/javascript/flavours/glitch/containers/status_container.js index f007c06df6..0be516a195 100644 --- a/app/javascript/flavours/glitch/containers/status_container.js +++ b/app/javascript/flavours/glitch/containers/status_container.js @@ -47,10 +47,7 @@ import { showAlertForError } from '../actions/alerts'; import AccountContainer from 'flavours/glitch/containers/account_container'; import Spoilers from '../components/spoilers'; import Icon from 'flavours/glitch/components/icon'; -import { createSelector } from 'reselect'; -import { Map as ImmutableMap } from 'immutable'; - -const customEmojiMap = createSelector([state => state.get('custom_emojis')], items => items.reduce((map, emoji) => map.set(emoji.get('shortcode'), emoji), ImmutableMap())); +import buildCustomEmojiMap from '../utils/emoji_map'; const messages = defineMessages({ deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' }, @@ -94,7 +91,7 @@ const makeMapStateToProps = () => { account: account || props.account, settings: state.get('local_settings'), prepend: prepend || props.prepend, - emojiMap: customEmojiMap(state), + emojiMap: buildCustomEmojiMap(state), pictureInPicture: getPictureInPicture(state, props), }; }; diff --git a/app/javascript/flavours/glitch/features/status/components/detailed_status.jsx b/app/javascript/flavours/glitch/features/status/components/detailed_status.jsx index 1770436ae7..00c11d6fa8 100644 --- a/app/javascript/flavours/glitch/features/status/components/detailed_status.jsx +++ b/app/javascript/flavours/glitch/features/status/components/detailed_status.jsx @@ -17,6 +17,7 @@ import { Icon } from 'flavours/glitch/components/icon'; import MediaGallery from 'flavours/glitch/components/media_gallery'; import PictureInPicturePlaceholder from 'flavours/glitch/components/picture_in_picture_placeholder'; import StatusContent from 'flavours/glitch/components/status_content'; +import StatusReactionsBar from '../../../components/status_reactions_bar'; import VisibilityIcon from 'flavours/glitch/components/status_visibility_icon'; import PollContainer from 'flavours/glitch/containers/poll_container'; import Audio from 'flavours/glitch/features/audio'; @@ -26,9 +27,6 @@ import scheduleIdleTask from '../../ui/util/schedule_idle_task'; import Card from './card'; - - - class DetailedStatus extends ImmutablePureComponent { static contextTypes = { @@ -53,6 +51,9 @@ class DetailedStatus extends ImmutablePureComponent { available: PropTypes.bool, }), onToggleMediaVisibility: PropTypes.func, + onReactionAdd: PropTypes.func.isRequired, + onReactionRemove: PropTypes.func.isRequired, + emojiMap: ImmutablePropTypes.map.isRequired, intl: PropTypes.object.isRequired, }; @@ -332,6 +333,14 @@ class DetailedStatus extends ImmutablePureComponent { disabled /> + +
diff --git a/app/javascript/flavours/glitch/features/status/index.jsx b/app/javascript/flavours/glitch/features/status/index.jsx index 0c2536f2ad..f4b96acc2b 100644 --- a/app/javascript/flavours/glitch/features/status/index.jsx +++ b/app/javascript/flavours/glitch/features/status/index.jsx @@ -29,6 +29,8 @@ import { unreblog, pin, unpin, + statusAddReaction, + statusRemoveReaction, } from 'flavours/glitch/actions/interactions'; import { changeLocalSetting } from 'flavours/glitch/actions/local_settings'; import { openModal } from 'flavours/glitch/actions/modal'; @@ -62,6 +64,8 @@ import { attachFullscreenListener, detachFullscreenListener, isFullscreen } from import ActionBar from './components/action_bar'; import DetailedStatus from './components/detailed_status'; +import buildCustomEmojiMap from '../../utils/emoji_map'; + const messages = defineMessages({ deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' }, deleteMessage: { id: 'confirmations.delete.message', defaultMessage: 'Are you sure you want to delete this status?' }, @@ -154,6 +158,7 @@ const makeMapStateToProps = () => { askReplyConfirmation: state.getIn(['local_settings', 'confirm_before_clearing_draft']) && state.getIn(['compose', 'text']).trim().length !== 0, domain: state.getIn(['meta', 'domain']), pictureInPicture: getPictureInPicture(state, { id: props.params.statusId }), + emojiMap: buildCustomEmojiMap(state), }; }; @@ -311,6 +316,30 @@ class Status extends ImmutablePureComponent { } }; + handleReactionAdd = (statusId, name) => { + const { dispatch } = this.props; + const { signedIn } = this.context.identity; + + if (signedIn) { + dispatch(statusAddReaction(statusId, name)); + } else { + dispatch(openModal('INTERACTION', { + type: 'reaction_add', + accountId: status.getIn(['account', 'id']), + url: status.get('url'), + })); + } + } + + handleReactionRemove = (statusId, name) => { + const { dispatch } = this.props; + const { signedIn } = this.context.identity; + + if (signedIn) { + dispatch(statusRemoveReaction(statusId, name)); + } + } + handlePin = (status) => { if (status.get('pinned')) { this.props.dispatch(unpin(status)); @@ -717,6 +746,8 @@ class Status extends ImmutablePureComponent { settings={settings} onOpenVideo={this.handleOpenVideo} onOpenMedia={this.handleOpenMedia} + onReactionAdd={this.handleReactionAdd} + onReactionRemove={this.handleReactionRemove} expanded={isExpanded} onToggleHidden={this.handleToggleHidden} onTranslate={this.handleTranslate} @@ -724,6 +755,7 @@ class Status extends ImmutablePureComponent { showMedia={this.state.showMedia} onToggleMediaVisibility={this.handleToggleMediaVisibility} pictureInPicture={pictureInPicture} + emojiMap={this.props.emojiMap} /> state.get('custom_emojis')], + items => items.reduce( + (map, emoji) => map.set(emoji.get('shortcode'), emoji), + ImmutableMap(), + ), +); +export default buildCustomEmojiMap;