mattermost-mobile/app/components/reactions/reactions.js
Farhan Munshi 217ef59f1c
[MM-23271] Check canAddReaction permission inside of render reactions (#4032)
* MM-23271 check canAddReaction when creating in reactions component

* MM-23271 Fixing linting
2020-03-16 11:29:13 -04:00

213 lines
6.4 KiB
JavaScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
import {
Image,
View,
} from 'react-native';
import {intlShape} from 'react-intl';
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
import TouchableWithFeedback from 'app/components/touchable_with_feedback';
import {preventDoubleTap} from 'app/utils/tap';
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
import {showModal, showModalOverCurrentContext} from 'app/actions/navigation';
import addReactionIcon from 'assets/images/icons/reaction.png';
import Reaction from './reaction';
export default class Reactions extends PureComponent {
static propTypes = {
actions: PropTypes.shape({
addReaction: PropTypes.func.isRequired,
getReactionsForPost: PropTypes.func.isRequired,
removeReaction: PropTypes.func.isRequired,
}).isRequired,
canAddReaction: PropTypes.bool,
canAddMoreReactions: PropTypes.bool,
canRemoveReaction: PropTypes.bool.isRequired,
currentUserId: PropTypes.string.isRequired,
position: PropTypes.oneOf(['right', 'left']),
postId: PropTypes.string.isRequired,
reactions: PropTypes.object,
theme: PropTypes.object.isRequired,
};
static defaultProps = {
position: 'right',
};
static contextTypes = {
intl: intlShape.isRequired,
};
componentDidMount() {
const {actions, postId, reactions} = this.props;
if (!reactions) {
actions.getReactionsForPost(postId);
}
}
handleAddReaction = preventDoubleTap(() => {
const {theme} = this.props;
const {formatMessage} = this.context.intl;
const screen = 'AddReaction';
const title = formatMessage({id: 'mobile.post_info.add_reaction', defaultMessage: 'Add Reaction'});
MaterialIcon.getImageSource('close', 20, theme.sidebarHeaderTextColor).then((source) => {
const passProps = {
closeButton: source,
onEmojiPress: this.handleAddReactionToPost,
};
showModal(screen, title, passProps);
});
});
handleAddReactionToPost = (emoji) => {
const {postId} = this.props;
this.props.actions.addReaction(postId, emoji);
};
handleReactionPress = (emoji, remove) => {
this.onPressDetected = true;
const {actions, postId} = this.props;
if (remove && this.props.canRemoveReaction) {
actions.removeReaction(postId, emoji);
} else if (!remove && this.props.canAddReaction) {
actions.addReaction(postId, emoji);
}
setTimeout(() => {
this.onPressDetected = false;
}, 300);
};
showReactionList = () => {
const {postId} = this.props;
const screen = 'ReactionList';
const passProps = {
postId,
};
if (!this.onPressDetected) {
showModalOverCurrentContext(screen, passProps);
}
};
renderReactions = () => {
const {currentUserId, reactions, theme, postId} = this.props;
const highlightedReactions = [];
const reactionsByName = Object.values(reactions).reduce((acc, reaction) => {
if (acc.has(reaction.emoji_name)) {
acc.get(reaction.emoji_name).push(reaction);
} else {
acc.set(reaction.emoji_name, [reaction]);
}
if (reaction.user_id === currentUserId) {
highlightedReactions.push(reaction.emoji_name);
}
return acc;
}, new Map());
return Array.from(reactionsByName.keys()).map((r) => {
return (
<Reaction
key={r}
count={reactionsByName.get(r).length}
emojiName={r}
highlight={highlightedReactions.includes(r)}
onPress={this.handleReactionPress}
onLongPress={this.showReactionList}
postId={postId}
theme={theme}
/>
);
});
};
render() {
const {position, reactions, canAddMoreReactions, canAddReaction} = this.props;
const styles = getStyleSheet(this.props.theme);
if (!reactions) {
return null;
}
let addMoreReactions = null;
if (canAddReaction && canAddMoreReactions) {
addMoreReactions = (
<TouchableWithFeedback
key='addReaction'
onPress={this.handleAddReaction}
style={[styles.reaction]}
type={'opacity'}
>
<Image
source={addReactionIcon}
style={styles.addReaction}
/>
</TouchableWithFeedback>
);
}
const reactionElements = [];
switch (position) {
case 'right':
reactionElements.push(
this.renderReactions(),
addMoreReactions,
);
break;
case 'left':
reactionElements.push(
addMoreReactions,
this.renderReactions(),
);
break;
}
return (
<View style={styles.reactionsContainer}>
{reactionElements}
</View>
);
}
}
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
return {
addReaction: {
tintColor: changeOpacity(theme.centerChannelColor, 0.5),
width: 23,
height: 20,
},
reaction: {
alignItems: 'center',
justifyContent: 'center',
borderRadius: 2,
borderColor: changeOpacity(theme.centerChannelColor, 0.3),
borderWidth: 1,
flexDirection: 'row',
height: 30,
marginRight: 6,
marginBottom: 5,
marginTop: 10,
paddingVertical: 2,
paddingHorizontal: 6,
width: 40,
},
reactionsContainer: {
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
alignContent: 'flex-start',
},
};
});