Interactions: optimistic Favourite and EmojiReact actions, fixes #104

This commit is contained in:
Alex Gleason 2020-09-27 17:24:55 -05:00
parent c77c89ea08
commit d5d8c4877e
No known key found for this signature in database
GPG key ID: 7211D1F99744FBB7
3 changed files with 66 additions and 5 deletions

View file

@ -2,6 +2,7 @@ import {
REBLOG_REQUEST, REBLOG_REQUEST,
REBLOG_FAIL, REBLOG_FAIL,
FAVOURITE_REQUEST, FAVOURITE_REQUEST,
UNFAVOURITE_REQUEST,
FAVOURITE_FAIL, FAVOURITE_FAIL,
} from '../actions/interactions'; } from '../actions/interactions';
import { import {
@ -12,11 +13,12 @@ import {
} from '../actions/statuses'; } from '../actions/statuses';
import { import {
EMOJI_REACT_REQUEST, EMOJI_REACT_REQUEST,
UNEMOJI_REACT_REQUEST,
} from '../actions/emoji_reacts'; } from '../actions/emoji_reacts';
import { TIMELINE_DELETE } from '../actions/timelines'; import { TIMELINE_DELETE } from '../actions/timelines';
import { STATUS_IMPORT, STATUSES_IMPORT } from '../actions/importer'; import { STATUS_IMPORT, STATUSES_IMPORT } from '../actions/importer';
import { Map as ImmutableMap, fromJS } from 'immutable'; import { Map as ImmutableMap, fromJS } from 'immutable';
import { simulateEmojiReact } from 'soapbox/utils/emoji_reacts'; import { simulateEmojiReact, simulateUnEmojiReact } from 'soapbox/utils/emoji_reacts';
const importStatus = (state, status) => state.set(status.id, fromJS(status)); const importStatus = (state, status) => state.set(status.id, fromJS(status));
@ -40,11 +42,27 @@ export default function statuses(state = initialState, action) {
case STATUSES_IMPORT: case STATUSES_IMPORT:
return importStatuses(state, action.statuses); return importStatuses(state, action.statuses);
case FAVOURITE_REQUEST: case FAVOURITE_REQUEST:
return state.setIn([action.status.get('id'), 'favourited'], true); return state.update(action.status.get('id'), status =>
status
.set('favourited', true)
.update('favourites_count', count => count + 1));
case UNFAVOURITE_REQUEST:
return state.update(action.status.get('id'), status =>
status
.set('favourited', false)
.update('favourites_count', count => Math.max(0, count - 1)));
case EMOJI_REACT_REQUEST: case EMOJI_REACT_REQUEST:
const path = [action.status.get('id'), 'pleroma', 'emoji_reactions']; return state
const emojiReacts = state.getIn(path); .updateIn(
return state.setIn(path, simulateEmojiReact(emojiReacts, action.emoji)); [action.status.get('id'), 'pleroma', 'emoji_reactions'],
emojiReacts => simulateEmojiReact(emojiReacts, action.emoji)
);
case UNEMOJI_REACT_REQUEST:
return state
.updateIn(
[action.status.get('id'), 'pleroma', 'emoji_reactions'],
emojiReacts => simulateUnEmojiReact(emojiReacts, action.emoji)
);
case FAVOURITE_FAIL: case FAVOURITE_FAIL:
return state.get(action.status.get('id')) === undefined ? state : state.setIn([action.status.get('id'), 'favourited'], false); return state.get(action.status.get('id')) === undefined ? state : state.setIn([action.status.get('id'), 'favourited'], false);
case REBLOG_REQUEST: case REBLOG_REQUEST:

View file

@ -6,6 +6,7 @@ import {
reduceEmoji, reduceEmoji,
getReactForStatus, getReactForStatus,
simulateEmojiReact, simulateEmojiReact,
simulateUnEmojiReact,
} from '../emoji_reacts'; } from '../emoji_reacts';
import { fromJS } from 'immutable'; import { fromJS } from 'immutable';
@ -205,3 +206,28 @@ describe('simulateEmojiReact', () => {
])); ]));
}); });
}); });
describe('simulateUnEmojiReact', () => {
it('removes the emoji from the list', () => {
const emojiReacts = fromJS([
{ 'count': 2, 'me': false, 'name': '👍' },
{ 'count': 3, 'me': true, 'name': '❤' },
]);
expect(simulateUnEmojiReact(emojiReacts, '❤')).toEqual(fromJS([
{ 'count': 2, 'me': false, 'name': '👍' },
{ 'count': 2, 'me': false, 'name': '❤' },
]));
});
it('removes the emoji if it\'s the last one in the list', () => {
const emojiReacts = fromJS([
{ 'count': 2, 'me': false, 'name': '👍' },
{ 'count': 2, 'me': false, 'name': '❤' },
{ 'count': 1, 'me': true, 'name': '😯' },
]);
expect(simulateUnEmojiReact(emojiReacts, '😯')).toEqual(fromJS([
{ 'count': 2, 'me': false, 'name': '👍' },
{ 'count': 2, 'me': false, 'name': '❤' },
]));
});
});

View file

@ -100,3 +100,20 @@ export const simulateEmojiReact = (emojiReacts, emoji) => {
})); }));
} }
}; };
export const simulateUnEmojiReact = (emojiReacts, emoji) => {
const idx = emojiReacts.findIndex(e =>
e.get('name') === emoji && e.get('me') === true);
if (idx > -1) {
const emojiReact = emojiReacts.get(idx);
const newCount = emojiReact.get('count') - 1;
if (newCount < 1) return emojiReacts.delete(idx);
return emojiReacts.set(idx, emojiReact.merge({
count: emojiReact.get('count') - 1,
me: false,
}));
} else {
return emojiReacts;
}
};