Change to not use the me attribute in emoji reactions
This commit is contained in:
parent
1c5d0b8ce1
commit
056f24fdc8
4 changed files with 28 additions and 18 deletions
|
@ -1,5 +1,6 @@
|
||||||
import api from '../api';
|
import api from '../api';
|
||||||
import { importFetchedAccounts, importFetchedStatus } from './importer';
|
import { importFetchedAccounts, importFetchedStatus } from './importer';
|
||||||
|
import { me } from '../initial_state';
|
||||||
|
|
||||||
export const REBLOG_REQUEST = 'REBLOG_REQUEST';
|
export const REBLOG_REQUEST = 'REBLOG_REQUEST';
|
||||||
export const REBLOG_SUCCESS = 'REBLOG_SUCCESS';
|
export const REBLOG_SUCCESS = 'REBLOG_SUCCESS';
|
||||||
|
@ -552,7 +553,7 @@ export function emojiReactionFail(status, name, domain, url, static_url, error)
|
||||||
};
|
};
|
||||||
|
|
||||||
const findMyEmojiReaction = (status) => {
|
const findMyEmojiReaction = (status) => {
|
||||||
return status.get('emoji_reactions').find(emoji_reaction => emoji_reaction.get('me') === true);
|
return status.get('emoji_reactioned') && status.get('emoji_reactions').find(emoji_reaction => emoji_reaction.get('account_ids').includes(me));
|
||||||
};
|
};
|
||||||
|
|
||||||
export function removeEmojiReaction(status) {
|
export function removeEmojiReaction(status) {
|
||||||
|
|
|
@ -7,7 +7,7 @@ import Emoji from './emoji';
|
||||||
import unicodeMapping from 'mastodon/features/emoji/emoji_unicode_mapping_light';
|
import unicodeMapping from 'mastodon/features/emoji/emoji_unicode_mapping_light';
|
||||||
import TransitionMotion from 'react-motion/lib/TransitionMotion';
|
import TransitionMotion from 'react-motion/lib/TransitionMotion';
|
||||||
import AnimatedNumber from 'mastodon/components/animated_number';
|
import AnimatedNumber from 'mastodon/components/animated_number';
|
||||||
import { reduceMotion } from 'mastodon/initial_state';
|
import { reduceMotion, me } from 'mastodon/initial_state';
|
||||||
import spring from 'react-motion/lib/spring';
|
import spring from 'react-motion/lib/spring';
|
||||||
|
|
||||||
class EmojiReaction extends ImmutablePureComponent {
|
class EmojiReaction extends ImmutablePureComponent {
|
||||||
|
@ -15,6 +15,7 @@ class EmojiReaction extends ImmutablePureComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
status: ImmutablePropTypes.map.isRequired,
|
status: ImmutablePropTypes.map.isRequired,
|
||||||
emojiReaction: ImmutablePropTypes.map.isRequired,
|
emojiReaction: ImmutablePropTypes.map.isRequired,
|
||||||
|
myReaction: PropTypes.bool.isRequired,
|
||||||
addEmojiReaction: PropTypes.func.isRequired,
|
addEmojiReaction: PropTypes.func.isRequired,
|
||||||
removeEmojiReaction: PropTypes.func.isRequired,
|
removeEmojiReaction: PropTypes.func.isRequired,
|
||||||
emojiMap: ImmutablePropTypes.map.isRequired,
|
emojiMap: ImmutablePropTypes.map.isRequired,
|
||||||
|
@ -26,9 +27,9 @@ class EmojiReaction extends ImmutablePureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
handleClick = () => {
|
handleClick = () => {
|
||||||
const { emojiReaction, status, addEmojiReaction, removeEmojiReaction } = this.props;
|
const { emojiReaction, status, addEmojiReaction, removeEmojiReaction, myReaction } = this.props;
|
||||||
|
|
||||||
if (emojiReaction.get('me')) {
|
if (myReaction) {
|
||||||
removeEmojiReaction(status);
|
removeEmojiReaction(status);
|
||||||
} else {
|
} else {
|
||||||
addEmojiReaction(status, emojiReaction.get('name'), emojiReaction.get('domain', null), emojiReaction.get('url', null), emojiReaction.get('static_url', null));
|
addEmojiReaction(status, emojiReaction.get('name'), emojiReaction.get('domain', null), emojiReaction.get('url', null), emojiReaction.get('static_url', null));
|
||||||
|
@ -40,7 +41,7 @@ class EmojiReaction extends ImmutablePureComponent {
|
||||||
handleMouseLeave = () => this.setState({ hovered: false })
|
handleMouseLeave = () => this.setState({ hovered: false })
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { emojiReaction, status } = this.props;
|
const { emojiReaction, status, myReaction } = this.props;
|
||||||
|
|
||||||
let shortCode = emojiReaction.get('name');
|
let shortCode = emojiReaction.get('name');
|
||||||
|
|
||||||
|
@ -49,7 +50,7 @@ class EmojiReaction extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button className={classNames('reactions-bar__item', { active: emojiReaction.get('me') })} disabled={status.get('emoji_reactioned') && !emojiReaction.get('me')} onClick={this.handleClick} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} title={`:${shortCode}:`} style={this.props.style}>
|
<button className={classNames('reactions-bar__item', { active: myReaction })} disabled={status.get('emoji_reactioned') && !myReaction} onClick={this.handleClick} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} title={`:${shortCode}:`} style={this.props.style}>
|
||||||
<span className='reactions-bar__item__emoji'><Emoji hovered={this.state.hovered} emoji={emojiReaction.get('name')} emojiMap={this.props.emojiMap} url={emojiReaction.get('url')} static_url={emojiReaction.get('static_url')} /></span>
|
<span className='reactions-bar__item__emoji'><Emoji hovered={this.state.hovered} emoji={emojiReaction.get('name')} emojiMap={this.props.emojiMap} url={emojiReaction.get('url')} static_url={emojiReaction.get('static_url')} /></span>
|
||||||
<span className='reactions-bar__item__count'><AnimatedNumber value={emojiReaction.get('count')} /></span>
|
<span className='reactions-bar__item__count'><AnimatedNumber value={emojiReaction.get('count')} /></span>
|
||||||
</button>
|
</button>
|
||||||
|
@ -80,16 +81,23 @@ export default class EmojiReactionsBar extends ImmutablePureComponent {
|
||||||
const emoji_reactions = status.get("emoji_reactions")
|
const emoji_reactions = status.get("emoji_reactions")
|
||||||
const visibleReactions = emoji_reactions.filter(x => x.get('count') > 0);
|
const visibleReactions = emoji_reactions.filter(x => x.get('count') > 0);
|
||||||
|
|
||||||
const styles = visibleReactions.map(emoji_reaction => ({
|
|
||||||
key: `${emoji_reaction.get('name')}@${emoji_reaction.get('domain', '')}`,
|
|
||||||
data: emoji_reaction,
|
|
||||||
style: { scale: reduceMotion ? 1 : spring(1, { stiffness: 150, damping: 13 }) },
|
|
||||||
})).toArray();
|
|
||||||
|
|
||||||
if (visibleReactions.isEmpty() ) {
|
if (visibleReactions.isEmpty() ) {
|
||||||
return <Fragment></Fragment>;
|
return <Fragment></Fragment>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const styles = visibleReactions.map(emoji_reaction => {
|
||||||
|
const domain = emoji_reaction.get('domain', '');
|
||||||
|
|
||||||
|
return {
|
||||||
|
key: `${emoji_reaction.get('name')}${domain ? `@${domain}` : ''}`,
|
||||||
|
data: {
|
||||||
|
emojiReaction: emoji_reaction,
|
||||||
|
myReaction: emoji_reaction.get('account_ids', []).includes(me),
|
||||||
|
},
|
||||||
|
style: { scale: reduceMotion ? 1 : spring(1, { stiffness: 150, damping: 13 }) },
|
||||||
|
};
|
||||||
|
}).toArray();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TransitionMotion styles={styles} willEnter={this.willEnter} willLeave={this.willLeave}>
|
<TransitionMotion styles={styles} willEnter={this.willEnter} willLeave={this.willLeave}>
|
||||||
{items => (
|
{items => (
|
||||||
|
@ -97,7 +105,8 @@ export default class EmojiReactionsBar extends ImmutablePureComponent {
|
||||||
{items.map(({ key, data, style }) => (
|
{items.map(({ key, data, style }) => (
|
||||||
<EmojiReaction
|
<EmojiReaction
|
||||||
key={key}
|
key={key}
|
||||||
emojiReaction={data}
|
emojiReaction={data.emojiReaction}
|
||||||
|
myReaction={data.myReaction}
|
||||||
style={{ transform: `scale(${style.scale})`, position: style.scale < 0.5 ? 'absolute' : 'static' }}
|
style={{ transform: `scale(${style.scale})`, position: style.scale < 0.5 ? 'absolute' : 'static' }}
|
||||||
status={this.props.status}
|
status={this.props.status}
|
||||||
addEmojiReaction={this.props.addEmojiReaction}
|
addEmojiReaction={this.props.addEmojiReaction}
|
||||||
|
@ -105,7 +114,6 @@ export default class EmojiReactionsBar extends ImmutablePureComponent {
|
||||||
emojiMap={this.props.emojiMap}
|
emojiMap={this.props.emojiMap}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
{visibleReactions.size < 8}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</TransitionMotion>
|
</TransitionMotion>
|
||||||
|
|
|
@ -23,6 +23,7 @@ import {
|
||||||
} from '../actions/statuses';
|
} from '../actions/statuses';
|
||||||
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 { me } from '../initial_state';
|
||||||
import { Map as ImmutableMap, fromJS } from 'immutable';
|
import { Map as ImmutableMap, fromJS } from 'immutable';
|
||||||
|
|
||||||
const importStatus = (state, status) => {
|
const importStatus = (state, status) => {
|
||||||
|
@ -55,15 +56,15 @@ const updateEmojiReaction = (state, id, name, domain, url, static_url, updater)
|
||||||
return emojiReactions.update(idx, emojiReactions => updater(emojiReactions));
|
return emojiReactions.update(idx, emojiReactions => updater(emojiReactions));
|
||||||
}
|
}
|
||||||
|
|
||||||
return emojiReactions.push(updater(fromJS({ name, domain, url, static_url, count: 0 })));
|
return emojiReactions.push(updater(fromJS({ name, domain, url, static_url, count: 0, account_ids: [] })));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const updateEmojiReactionCount = (state, emojiReaction) => updateEmojiReaction(state, emojiReaction.status_id, emojiReaction.name, emojiReaction.domain, emojiReaction.url, emojiReaction.static_url, x => x.set('count', emojiReaction.count));
|
const updateEmojiReactionCount = (state, emojiReaction) => updateEmojiReaction(state, emojiReaction.status_id, emojiReaction.name, emojiReaction.domain, emojiReaction.url, emojiReaction.static_url, x => x.set('count', emojiReaction.count));
|
||||||
|
|
||||||
const addEmojiReaction = (state, id, name, domain, url, static_url) => updateEmojiReaction(state, id, name, domain, url, static_url, x => x.set('me', true).update('count', y => y + 1));
|
const addEmojiReaction = (state, id, name, domain, url, static_url) => updateEmojiReaction(state, id, name, domain, url, static_url, x => x.update('count', y => y + 1).update('account_ids', z => z.push(me)));
|
||||||
|
|
||||||
const removeEmojiReaction = (state, id, name, domain, url, static_url) => updateEmojiReaction(state, id, name, domain, url, static_url, x => x.set('me', false).update('count', y => y - 1));
|
const removeEmojiReaction = (state, id, name, domain, url, static_url) => updateEmojiReaction(state, id, name, domain, url, static_url, x => x.update('count', y => y - 1).update('account_ids', z => z.deleteIn([me])));
|
||||||
|
|
||||||
const initialState = ImmutableMap();
|
const initialState = ImmutableMap();
|
||||||
|
|
||||||
|
|
|
@ -311,7 +311,7 @@ class Status < ApplicationRecord
|
||||||
|
|
||||||
def generate_grouped_emoji_reactions
|
def generate_grouped_emoji_reactions
|
||||||
records = emoji_reactions.group(:status_id, :name, :custom_emoji_id).order(Arel.sql('MIN(created_at) ASC')).select('name, custom_emoji_id, count(*) as count, array_agg(account_id::text order by created_at) as account_ids')
|
records = emoji_reactions.group(:status_id, :name, :custom_emoji_id).order(Arel.sql('MIN(created_at) ASC')).select('name, custom_emoji_id, count(*) as count, array_agg(account_id::text order by created_at) as account_ids')
|
||||||
ActiveModelSerializers::SerializableResource.new(records, each_serializer: REST::EmojiReactionSerializer, scope: nil, scope_name: :current_user).to_json
|
Oj.dump(ActiveModelSerializers::SerializableResource.new(records, each_serializer: REST::EmojiReactionSerializer, scope: nil, scope_name: :current_user))
|
||||||
end
|
end
|
||||||
|
|
||||||
def refresh_grouped_emoji_reactions!
|
def refresh_grouped_emoji_reactions!
|
||||||
|
|
Loading…
Reference in a new issue