diff --git a/app/gabsocial/actions/emoji_reacts.js b/app/gabsocial/actions/emoji_reacts.js
index 0b61d1eb4..3443165d2 100644
--- a/app/gabsocial/actions/emoji_reacts.js
+++ b/app/gabsocial/actions/emoji_reacts.js
@@ -13,9 +13,11 @@ export const EMOJI_REACTS_FETCH_REQUEST = 'EMOJI_REACTS_FETCH_REQUEST';
export const EMOJI_REACTS_FETCH_SUCCESS = 'EMOJI_REACTS_FETCH_SUCCESS';
export const EMOJI_REACTS_FETCH_FAIL = 'EMOJI_REACTS_FETCH_FAIL';
+const noOp = () => () => new Promise(f => f());
+
export function fetchEmojiReacts(id, emoji) {
return (dispatch, getState) => {
- if (!getState().get('me')) return;
+ if (!getState().get('me')) return dispatch(noOp());
dispatch(fetchEmojiReactsRequest(id, emoji));
@@ -23,7 +25,7 @@ export function fetchEmojiReacts(id, emoji) {
? `/api/v1/pleroma/statuses/${id}/reactions/${emoji}`
: `/api/v1/pleroma/statuses/${id}/reactions`;
- api(getState).get(url).then(response => {
+ return api(getState).get(url).then(response => {
response.data.forEach(emojiReact => {
dispatch(importFetchedAccounts(emojiReact.accounts));
});
@@ -36,11 +38,11 @@ export function fetchEmojiReacts(id, emoji) {
export function emojiReact(status, emoji) {
return function(dispatch, getState) {
- if (!getState().get('me')) return;
+ if (!getState().get('me')) return dispatch(noOp());
dispatch(emojiReactRequest(status, emoji));
- api(getState)
+ return api(getState)
.put(`/api/v1/pleroma/statuses/${status.get('id')}/reactions/${emoji}`)
.then(function(response) {
dispatch(importFetchedStatus(response.data));
@@ -53,11 +55,11 @@ export function emojiReact(status, emoji) {
export function unEmojiReact(status, emoji) {
return (dispatch, getState) => {
- if (!getState().get('me')) return;
+ if (!getState().get('me')) return dispatch(noOp());
dispatch(unEmojiReactRequest(status, emoji));
- api(getState)
+ return api(getState)
.delete(`/api/v1/pleroma/statuses/${status.get('id')}/reactions/${emoji}`)
.then(response => {
dispatch(importFetchedStatus(response.data));
diff --git a/app/gabsocial/components/icon_button.js b/app/gabsocial/components/icon_button.js
index ceb2a643c..c0561bf9e 100644
--- a/app/gabsocial/components/icon_button.js
+++ b/app/gabsocial/components/icon_button.js
@@ -4,6 +4,7 @@ import spring from 'react-motion/lib/spring';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import Icon from 'gabsocial/components/icon';
+import emojify from 'gabsocial/features/emoji/emoji';
export default class IconButton extends React.PureComponent {
@@ -24,6 +25,7 @@ export default class IconButton extends React.PureComponent {
overlay: PropTypes.bool,
tabIndex: PropTypes.string,
text: PropTypes.string,
+ emoji: PropTypes.string,
};
static defaultProps = {
@@ -66,6 +68,7 @@ export default class IconButton extends React.PureComponent {
tabIndex,
title,
text,
+ emoji,
} = this.props;
const classes = classNames(className, 'icon-button', {
@@ -90,7 +93,9 @@ export default class IconButton extends React.PureComponent {
disabled={disabled}
>
{text && {text}}
@@ -111,7 +116,9 @@ export default class IconButton extends React.PureComponent {
disabled={disabled}
>
{text && {text}}
diff --git a/app/gabsocial/features/status/components/action_bar.js b/app/gabsocial/features/status/components/action_bar.js
index f6dd17aa8..d1f9fa333 100644
--- a/app/gabsocial/features/status/components/action_bar.js
+++ b/app/gabsocial/features/status/components/action_bar.js
@@ -9,6 +9,7 @@ import DropdownMenuContainer from '../../../containers/dropdown_menu_container';
import { defineMessages, injectIntl } from 'react-intl';
import { isStaff } from 'gabsocial/utils/accounts';
import EmojiSelector from 'gabsocial/components/emoji_selector';
+import { getReactForStatus } from 'gabsocial/utils/emoji_reacts';
const messages = defineMessages({
delete: { id: 'status.delete', defaultMessage: 'Delete' },
@@ -189,6 +190,7 @@ class ActionBar extends React.PureComponent {
const publicStatus = ['public', 'unlisted'].includes(status.get('visibility'));
const mutingConversation = status.get('muted');
+ const meEmojiReact = getReactForStatus(status);
let menu = [];
@@ -267,10 +269,12 @@ class ActionBar extends React.PureComponent {
diff --git a/app/gabsocial/features/status/components/status_interaction_bar.js b/app/gabsocial/features/status/components/status_interaction_bar.js
index 4e4a7fd54..711fcf493 100644
--- a/app/gabsocial/features/status/components/status_interaction_bar.js
+++ b/app/gabsocial/features/status/components/status_interaction_bar.js
@@ -2,18 +2,20 @@ import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
import emojify from 'gabsocial/features/emoji/emoji';
import { reduceEmoji } from 'gabsocial/utils/emoji_reacts';
+import SoapboxPropTypes from 'gabsocial/utils/soapbox_prop_types';
export class StatusInteractionBar extends React.Component {
static propTypes = {
status: ImmutablePropTypes.map,
+ me: SoapboxPropTypes.me,
}
getNormalizedReacts = () => {
- const { status } = this.props;
+ const { status, me } = this.props;
const emojiReacts = status.getIn(['pleroma', 'emoji_reactions']);
const favouritesCount = status.get('favourites_count');
- return reduceEmoji(emojiReacts, favouritesCount).reverse();
+ return reduceEmoji(emojiReacts, favouritesCount, me).reverse();
}
render() {
diff --git a/app/gabsocial/features/status/index.js b/app/gabsocial/features/status/index.js
index ae648d4ce..ee631e812 100644
--- a/app/gabsocial/features/status/index.js
+++ b/app/gabsocial/features/status/index.js
@@ -163,17 +163,20 @@ class Status extends ImmutablePureComponent {
}
handleEmojiReactClick = (status, emoji) => {
- if (emoji === '👍') {
- this.handleFavouriteClick(status); return;
- }
- const hasReaction = status.getIn(['pleroma', 'emoji_reactions'])
- .findIndex(e => e.get('name') === emoji && e.get('me') === true) > -1;
-
- if (hasReaction) {
- this.props.dispatch(unEmojiReact(status, emoji));
- } else {
- this.props.dispatch(emojiReact(status, emoji));
- }
+ Promise.all(status.getIn(['pleroma', 'emoji_reactions'])
+ .filter(emojiReact => emojiReact.get('me') === true)
+ .map(emojiReact =>
+ this.props.dispatch(unEmojiReact(status, emojiReact.get('name')))))
+ .then(() => {
+ if (emoji === '👍') {
+ this.handleFavouriteClick(status); return;
+ } else {
+ this.props.dispatch(emojiReact(status, emoji));
+ }
+ })
+ .catch(err => {
+ console.error(err);
+ });
}
handleFavouriteClick = (status) => {
diff --git a/app/gabsocial/utils/__tests__/emoji_reacts-test.js b/app/gabsocial/utils/__tests__/emoji_reacts-test.js
index 639e0795c..e1a09ea94 100644
--- a/app/gabsocial/utils/__tests__/emoji_reacts-test.js
+++ b/app/gabsocial/utils/__tests__/emoji_reacts-test.js
@@ -154,4 +154,19 @@ describe('getReactForStatus', () => {
const status = fromJS({ favourites_count: 1, favourited: true });
expect(getReactForStatus(status)).toEqual('👍');
});
+
+ it('returns undefined when a status has no reacts (or favourites)', () => {
+ const status = fromJS([]);
+ expect(getReactForStatus(status)).toEqual(undefined);
+ });
+
+ it('returns undefined when a status has no valid reacts (or favourites)', () => {
+ const status = fromJS([
+ { 'count': 1, 'me': true, 'name': '🔪' },
+ { 'count': 1, 'me': true, 'name': '🌵' },
+ { 'count': 1, 'me': false, 'name': '👀' },
+ { 'count': 1, 'me': false, 'name': '🍩' },
+ ]);
+ expect(getReactForStatus(status)).toEqual(undefined);
+ });
});
diff --git a/app/gabsocial/utils/emoji_reacts.js b/app/gabsocial/utils/emoji_reacts.js
index e9712e6ca..bbdaaf474 100644
--- a/app/gabsocial/utils/emoji_reacts.js
+++ b/app/gabsocial/utils/emoji_reacts.js
@@ -79,7 +79,6 @@ export const getReactForStatus = status => {
status.getIn(['pleroma', 'emoji_reactions'], ImmutableList()),
status.get('favourites_count'),
status.get('favourited')
- ).filter(e => e.get('me'))
- .first(ImmutableMap())
- .get('name');
+ ).filter(e => e.get('me') === true)
+ .getIn([0, 'name']);
};