Add emojiReact utils with tests
This commit is contained in:
parent
11c9f153e1
commit
d562a25c78
|
@ -1,16 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import emojify from 'gabsocial/features/emoji/emoji';
|
import emojify from 'gabsocial/features/emoji/emoji';
|
||||||
|
import { reduceEmoji } from 'gabsocial/utils/emoji_reacts';
|
||||||
// https://emojipedia.org/facebook/
|
|
||||||
const ALLOWED_EMOJI = [
|
|
||||||
'👍',
|
|
||||||
'❤️',
|
|
||||||
'😂',
|
|
||||||
'😯',
|
|
||||||
'😢',
|
|
||||||
'😡',
|
|
||||||
];
|
|
||||||
|
|
||||||
export class StatusInteractionBar extends React.Component {
|
export class StatusInteractionBar extends React.Component {
|
||||||
|
|
||||||
|
@ -18,35 +9,15 @@ export class StatusInteractionBar extends React.Component {
|
||||||
status: ImmutablePropTypes.map,
|
status: ImmutablePropTypes.map,
|
||||||
}
|
}
|
||||||
|
|
||||||
sortEmoji = emojiReacts => (
|
|
||||||
emojiReacts // TODO: Sort by count
|
|
||||||
);
|
|
||||||
|
|
||||||
mergeEmoji = emojiReacts => (
|
|
||||||
emojiReacts // TODO: Merge similar emoji
|
|
||||||
);
|
|
||||||
|
|
||||||
filterEmoji = emojiReacts => (
|
|
||||||
emojiReacts.filter(emojiReact => (
|
|
||||||
ALLOWED_EMOJI.includes(emojiReact.get('name'))
|
|
||||||
)))
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { status } = this.props;
|
const { status } = this.props;
|
||||||
const emojiReacts = status.getIn(['pleroma', 'emoji_reactions']);
|
const emojiReacts = status.getIn(['pleroma', 'emoji_reactions']);
|
||||||
const likeCount = status.get('favourites_count');
|
const favouritesCount = status.get('favourites_count');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className='emoji-reacts'>
|
||||||
{likeCount > 0 && <span className='emoji-react'>
|
{reduceEmoji(emojiReacts, favouritesCount).map((e, i) => (
|
||||||
<span
|
<span className='emoji-react' key={i}>
|
||||||
className='emoji-react--emoji'
|
|
||||||
dangerouslySetInnerHTML={{ __html: emojify('👍') }}
|
|
||||||
/>
|
|
||||||
<span className='emoji-react--count'>{likeCount}</span>
|
|
||||||
</span>}
|
|
||||||
{this.filterEmoji(emojiReacts).map(e => (
|
|
||||||
<span className='emoji-react'>
|
|
||||||
<span
|
<span
|
||||||
className='emoji-react--emoji'
|
className='emoji-react--emoji'
|
||||||
dangerouslySetInnerHTML={{ __html: emojify(e.get('name')) }}
|
dangerouslySetInnerHTML={{ __html: emojify(e.get('name')) }}
|
||||||
|
@ -54,7 +25,7 @@ export class StatusInteractionBar extends React.Component {
|
||||||
<span className='emoji-react--count'>{e.get('count')}</span>
|
<span className='emoji-react--count'>{e.get('count')}</span>
|
||||||
</span>
|
</span>
|
||||||
))}
|
))}
|
||||||
</>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
import {
|
||||||
|
sortEmoji,
|
||||||
|
mergeEmojiFavourites,
|
||||||
|
filterEmoji,
|
||||||
|
reduceEmoji,
|
||||||
|
} from '../emoji_reacts';
|
||||||
|
import { fromJS } from 'immutable';
|
||||||
|
|
||||||
|
describe('filterEmoji', () => {
|
||||||
|
describe('with a mix of allowed and disallowed emoji', () => {
|
||||||
|
const emojiReacts = fromJS([
|
||||||
|
{ 'count': 1, 'me': true, 'name': '🌵' },
|
||||||
|
{ 'count': 1, 'me': true, 'name': '😂' },
|
||||||
|
{ 'count': 1, 'me': true, 'name': '👀' },
|
||||||
|
{ 'count': 1, 'me': true, 'name': '🍩' },
|
||||||
|
{ 'count': 1, 'me': true, 'name': '😡' },
|
||||||
|
{ 'count': 1, 'me': true, 'name': '🔪' },
|
||||||
|
{ 'count': 1, 'me': true, 'name': '😠' },
|
||||||
|
]);
|
||||||
|
it('filters only allowed emoji', () => {
|
||||||
|
expect(filterEmoji(emojiReacts)).toEqual(fromJS([
|
||||||
|
{ 'count': 1, 'me': true, 'name': '😂' },
|
||||||
|
{ 'count': 1, 'me': true, 'name': '😡' },
|
||||||
|
]));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('sortEmoji', () => {
|
||||||
|
describe('with an unsorted list of emoji', () => {
|
||||||
|
const emojiReacts = fromJS([
|
||||||
|
{ 'count': 7, 'me': true, 'name': '😯' },
|
||||||
|
{ 'count': 3, 'me': true, 'name': '😢' },
|
||||||
|
{ 'count': 1, 'me': true, 'name': '😡' },
|
||||||
|
{ 'count': 20, 'me': true, 'name': '👍' },
|
||||||
|
{ 'count': 7, 'me': true, 'name': '😂' },
|
||||||
|
{ 'count': 15, 'me': true, 'name': '❤️' },
|
||||||
|
]);
|
||||||
|
it('sorts the emoji by count', () => {
|
||||||
|
expect(sortEmoji(emojiReacts)).toEqual(fromJS([
|
||||||
|
{ 'count': 20, 'me': true, 'name': '👍' },
|
||||||
|
{ 'count': 15, 'me': true, 'name': '❤️' },
|
||||||
|
{ 'count': 7, 'me': true, 'name': '😯' },
|
||||||
|
{ 'count': 7, 'me': true, 'name': '😂' },
|
||||||
|
{ 'count': 3, 'me': true, 'name': '😢' },
|
||||||
|
{ 'count': 1, 'me': true, 'name': '😡' },
|
||||||
|
]));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('mergeEmojiFavourites', () => {
|
||||||
|
const favouritesCount = 12;
|
||||||
|
|
||||||
|
describe('with existing 👍 reacts', () => {
|
||||||
|
const emojiReacts = fromJS([
|
||||||
|
{ 'count': 20, 'me': true, 'name': '👍' },
|
||||||
|
{ 'count': 15, 'me': true, 'name': '❤️' },
|
||||||
|
{ 'count': 7, 'me': true, 'name': '😯' },
|
||||||
|
]);
|
||||||
|
it('combines 👍 reacts with favourites', () => {
|
||||||
|
expect(mergeEmojiFavourites(emojiReacts, favouritesCount)).toEqual(fromJS([
|
||||||
|
{ 'count': 32, 'me': true, 'name': '👍' },
|
||||||
|
{ 'count': 15, 'me': true, 'name': '❤️' },
|
||||||
|
{ 'count': 7, 'me': true, 'name': '😯' },
|
||||||
|
]));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('without existing 👍 reacts', () => {
|
||||||
|
const emojiReacts = fromJS([
|
||||||
|
{ 'count': 15, 'me': true, 'name': '❤️' },
|
||||||
|
{ 'count': 7, 'me': true, 'name': '😯' },
|
||||||
|
]);
|
||||||
|
it('adds 👍 reacts to the map equaling favourite count', () => {
|
||||||
|
expect(mergeEmojiFavourites(emojiReacts, favouritesCount)).toEqual(fromJS([
|
||||||
|
{ 'count': 15, 'me': true, 'name': '❤️' },
|
||||||
|
{ 'count': 7, 'me': true, 'name': '😯' },
|
||||||
|
{ 'count': 12, 'me': false, 'name': '👍' },
|
||||||
|
]));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('reduceEmoji', () => {
|
||||||
|
describe('with a clusterfuck of emoji', () => {
|
||||||
|
const emojiReacts = fromJS([
|
||||||
|
{ 'count': 1, 'me': false, 'name': '😡' },
|
||||||
|
{ 'count': 1, 'me': true, 'name': '🔪' },
|
||||||
|
{ 'count': 7, 'me': true, 'name': '😯' },
|
||||||
|
{ 'count': 3, 'me': false, 'name': '😢' },
|
||||||
|
{ 'count': 1, 'me': true, 'name': '🌵' },
|
||||||
|
{ 'count': 20, 'me': true, 'name': '👍' },
|
||||||
|
{ 'count': 7, 'me': false, 'name': '😂' },
|
||||||
|
{ 'count': 15, 'me': true, 'name': '❤️' },
|
||||||
|
{ 'count': 1, 'me': false, 'name': '👀' },
|
||||||
|
{ 'count': 1, 'me': false, 'name': '🍩' },
|
||||||
|
]);
|
||||||
|
it('sorts, filters, and combines emoji and favourites', () => {
|
||||||
|
expect(reduceEmoji(emojiReacts, 7)).toEqual(fromJS([
|
||||||
|
{ 'count': 27, 'me': true, 'name': '👍' },
|
||||||
|
{ 'count': 15, 'me': true, 'name': '❤️' },
|
||||||
|
{ 'count': 7, 'me': true, 'name': '😯' },
|
||||||
|
{ 'count': 7, 'me': false, 'name': '😂' },
|
||||||
|
{ 'count': 3, 'me': false, 'name': '😢' },
|
||||||
|
{ 'count': 1, 'me': false, 'name': '😡' },
|
||||||
|
]));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,40 @@
|
||||||
|
import { Map as ImmutableMap } from 'immutable';
|
||||||
|
|
||||||
|
// https://emojipedia.org/facebook/
|
||||||
|
export const ALLOWED_EMOJI = [
|
||||||
|
'👍',
|
||||||
|
'❤️',
|
||||||
|
'😂',
|
||||||
|
'😯',
|
||||||
|
'😢',
|
||||||
|
'😡',
|
||||||
|
];
|
||||||
|
|
||||||
|
export const sortEmoji = emojiReacts => (
|
||||||
|
emojiReacts.sortBy(emojiReact => -emojiReact.get('count'))
|
||||||
|
);
|
||||||
|
|
||||||
|
export const mergeEmoji = emojiReacts => (
|
||||||
|
emojiReacts // TODO: Merge similar emoji
|
||||||
|
);
|
||||||
|
|
||||||
|
export const mergeEmojiFavourites = (emojiReacts, favouritesCount) => {
|
||||||
|
const likeIndex = emojiReacts.findIndex(emojiReact =>
|
||||||
|
emojiReact.get('name') === '👍');
|
||||||
|
if (likeIndex > -1) {
|
||||||
|
const likeCount = emojiReacts.getIn([likeIndex, 'count']);
|
||||||
|
return emojiReacts.setIn([likeIndex, 'count'], likeCount + favouritesCount);
|
||||||
|
} else {
|
||||||
|
return emojiReacts.push(ImmutableMap({ count: favouritesCount, me: false, name: '👍' }));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const filterEmoji = emojiReacts => (
|
||||||
|
emojiReacts.filter(emojiReact => (
|
||||||
|
ALLOWED_EMOJI.includes(emojiReact.get('name'))
|
||||||
|
)));
|
||||||
|
|
||||||
|
export const reduceEmoji = (emojiReacts, favouritesCount) => (
|
||||||
|
sortEmoji(filterEmoji(mergeEmoji(mergeEmojiFavourites(
|
||||||
|
emojiReacts, favouritesCount
|
||||||
|
)))));
|
Loading…
Reference in New Issue