2017-06-08_509bba0/509bba0_unpacked_with_node_modules/discord_app/components/MessageReactions.js
2022-07-26 10:06:20 -07:00

169 lines
4.5 KiB
JavaScript
Executable file

/* @flow */
import React from 'react';
import lodash from 'lodash';
import TransitionGroup from '../lib/transitions/TransitionGroup';
import Animated from '../lib/animated';
import classNames from 'classnames';
import Tooltip from './common/Tooltip';
import AnimatedCounter from './common/animated/AnimatedCounter';
import {addReaction, removeReaction} from '../actions/ReactionActionCreators';
import AvatarUtils from '../utils/AvatarUtils';
import EmojiUtils from '../utils/EmojiUtils';
import MessageReactionsStore from '../stores/MessageReactionsStore';
import WindowStore from '../stores/WindowStore';
import type MessageRecord from '../records/MessageRecord';
import {getReactionTooltip} from '../utils/ReactionUtils';
import './MessageReactions.styl';
class Reaction extends React.PureComponent {
props: {
me: boolean,
readOnly: boolean,
emoji: {
id: ?string,
name: string,
},
message: MessageRecord,
count: number,
};
state: {
tooltipText: string,
};
scale: Animated.Value;
opacity: Animated.Value;
timeout: ?number;
constructor(props) {
super(props);
this.state = {
tooltipText: '',
};
this.scale = new Animated.Value(1);
this.opacity = new Animated.Value(1);
lodash.bindAll(this, ['handleClick', 'handleMouseOver', 'handleMouseOut', 'handleStoreChange']);
}
componentWillAppear(callback) {
this.animateIn(callback);
}
componentWillEnter(callback) {
this.animateIn(callback);
}
componentWillUnmount() {
this.handleMouseOut();
}
animateIn(callback) {
if (WindowStore.isFocused()) {
this.scale.setValue(0);
this.opacity.setValue(0);
Animated.parallel([
Animated.timing(this.scale, {
toValue: 1,
duration: 300,
easing: Animated.Easing.inOut(Animated.Easing.back()),
}),
Animated.timing(this.opacity, {
toValue: 1,
duration: 300,
}),
]).start(callback);
} else {
this.scale.setValue(1);
this.opacity.setValue(1);
callback();
}
}
handleClick() {
const {message, emoji, me, readOnly} = this.props;
const channelId = message.getChannelId();
if (me) {
removeReaction(channelId, message.id, emoji);
} else if (!readOnly) {
addReaction(channelId, message.id, emoji);
}
}
handleMouseOver() {
this.timeout =
this.timeout ||
setTimeout(() => {
this.timeout = null;
this.handleStoreChange();
MessageReactionsStore.addChangeListener(this.handleStoreChange);
}, 500);
}
handleMouseOut() {
if (this.timeout != null) {
clearTimeout(this.timeout);
this.timeout = null;
this.setState({
tooltipText: '',
});
}
MessageReactionsStore.removeChangeListener(this.handleStoreChange);
}
handleStoreChange() {
const {message, emoji} = this.props;
this.setState({
tooltipText: getReactionTooltip(message, emoji),
});
}
render() {
const {count, emoji, me, readOnly} = this.props;
const src = emoji.id == null ? EmojiUtils.getURL(emoji.name) : AvatarUtils.getEmojiURL({id: emoji.id});
const style = {
transform: [{scale: this.scale}],
opacity: this.opacity,
};
return (
<Tooltip text={this.state.tooltipText} hideOnClick={false}>
<Animated.div
className={classNames('reaction', {'reaction-me': me, 'reaction-read-only': readOnly})}
onClick={this.handleClick}
onMouseOver={this.handleMouseOver}
onMouseOut={this.handleMouseOut}
style={style}>
{src
? <img className="emoji" src={src} alt={emoji.name} />
: <span className="emoji emoji-text">{emoji.name}</span>}
<AnimatedCounter className="reaction-count" value={count} digitWidth={9} />
</Animated.div>
</Tooltip>
);
}
}
export default class Reactions extends React.PureComponent {
render() {
const {message, transitionAppear, readOnly} = this.props;
return (
<TransitionGroup className="reactions" transitionAppear={transitionAppear} transitionLeave={false}>
{message.reactions.map(reaction =>
<Reaction
key={`${reaction.emoji.id}:${reaction.emoji.name}`}
message={message}
readOnly={readOnly}
{...reaction}
/>
)}
{this.props.children}
</TransitionGroup>
);
}
}
// WEBPACK FOOTER //
// ./discord_app/components/MessageReactions.js