Files
mattermost-mobile/app/screens/reaction_list/reaction_list.js
Saturnino Abril ce47c23100 [MM-9490] Add reaction list (#2125)
* add reaction list

* update styles and add tests

* update styles

* update per comment
2018-09-27 21:54:17 +08:00

211 lines
6.3 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 {View} from 'react-native';
import {intlShape} from 'react-intl';
import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scroll-view';
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
import {
generateUserProfilesById,
getMissingUserIds,
getReactionsByName,
getSortedReactionsForHeader,
getUniqueUserIds,
sortReactions,
} from 'app/utils/reaction';
import ReactionHeader from './reaction_header';
import ReactionRow from './reaction_row';
import {ALL_EMOJIS} from 'app/constants/emoji';
export default class ReactionList extends PureComponent {
static propTypes = {
actions: PropTypes.shape({
getMissingProfilesByIds: PropTypes.func.isRequired,
}).isRequired,
navigator: PropTypes.object,
reactions: PropTypes.array.isRequired,
theme: PropTypes.object.isRequired,
teammateNameDisplay: PropTypes.string,
userProfiles: PropTypes.array,
};
static contextTypes = {
intl: intlShape.isRequired,
};
constructor(props) {
super(props);
const {reactions, userProfiles} = props;
const reactionsByName = getReactionsByName(reactions);
this.state = {
allUserIds: getUniqueUserIds(reactions),
reactions,
reactionsByName,
selected: ALL_EMOJIS,
sortedReactions: sortReactions(reactionsByName),
sortedReactionsForHeader: getSortedReactionsForHeader(reactionsByName),
userProfiles,
userProfilesById: generateUserProfilesById(userProfiles),
};
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
}
static getDerivedStateFromProps(nextProps, prevState) {
let newState = null;
if (nextProps.reactions !== prevState.reactions) {
const {reactions} = nextProps;
const reactionsByName = getReactionsByName(reactions);
newState = {
allUserIds: getUniqueUserIds(reactions),
reactions,
reactionsByName,
sortedReactions: sortReactions(reactionsByName),
sortedReactionsForHeader: getSortedReactionsForHeader(reactionsByName),
};
}
if (nextProps.userProfiles !== prevState.userProfiles) {
const userProfilesById = generateUserProfilesById(nextProps.userProfiles);
if (newState) {
newState.userProfilesById = userProfilesById;
} else {
newState = {userProfilesById};
}
}
return newState;
}
componentDidMount() {
this.getMissingProfiles();
}
componentDidUpdate(_, prevState) {
if (prevState.allUserIds !== this.state.allUserIds) {
this.getMissingProfiles();
}
}
onNavigatorEvent = (event) => {
if (event.type === 'NavBarButtonPress') {
if (event.id === 'close-reaction-list') {
this.props.navigator.dismissModal({
animationType: 'slide-down',
});
}
}
};
getMissingProfiles = () => {
const {allUserIds, userProfiles, userProfilesById} = this.state;
if (userProfiles.length !== allUserIds.length) {
const missingUserIds = getMissingUserIds(userProfilesById, allUserIds);
if (missingUserIds.length > 0) {
this.props.actions.getMissingProfilesByIds(missingUserIds);
}
}
}
scrollViewRef = (ref) => {
this.scrollView = ref;
};
handleOnSelectReaction = (emoji) => {
this.setState({selected: emoji});
}
renderReactionRows = () => {
const {
navigator,
teammateNameDisplay,
theme,
} = this.props;
const {
reactionsByName,
selected,
sortedReactions,
userProfilesById,
} = this.state;
const style = getStyleSheet(theme);
const reactions = selected === ALL_EMOJIS ? sortedReactions : reactionsByName[selected];
return reactions.map(({emoji_name: emojiName, user_id: userId}) => (
<View
key={emojiName + userId}
style={style.rowContainer}
>
<ReactionRow
emojiName={emojiName}
navigator={navigator}
teammateNameDisplay={teammateNameDisplay}
theme={theme}
user={userProfilesById[userId]}
/>
<View style={style.separator}/>
</View>
));
}
render() {
const {
theme,
} = this.props;
const {
selected,
sortedReactionsForHeader,
} = this.state;
const style = getStyleSheet(theme);
return (
<View style={style.flex}>
<View style={style.headerContainer}>
<ReactionHeader
selected={selected}
onSelectReaction={this.handleOnSelectReaction}
reactions={sortedReactionsForHeader}
theme={theme}
/>
</View>
<KeyboardAwareScrollView
bounces={true}
innerRef={this.scrollViewRef}
>
{this.renderReactionRows()}
</KeyboardAwareScrollView>
</View>
);
}
}
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
return {
flex: {
backgroundColor: theme.centerChannelBg,
flex: 1,
},
headerContainer: {
height: 38,
borderColor: changeOpacity(theme.centerChannelColor, 0.2),
borderBottomWidth: 1,
},
rowContainer: {
justifyContent: 'center',
height: 45,
},
separator: {
height: 1,
backgroundColor: changeOpacity(theme.centerChannelColor, 0.2),
},
};
});