2018-01-30 19:48:26 +00:00
|
|
|
import React from 'react';
|
|
|
|
import PropTypes from 'prop-types';
|
2019-01-29 19:52:56 +00:00
|
|
|
import { Text, TouchableOpacity } from 'react-native';
|
2019-09-16 20:50:51 +00:00
|
|
|
import { shortnameToUnicode } from 'emoji-toolkit';
|
2018-01-30 19:48:26 +00:00
|
|
|
import { responsive } from 'react-native-responsive-ui';
|
2018-02-08 14:08:50 +00:00
|
|
|
import { OptimizedFlatList } from 'react-native-optimized-flatlist';
|
2019-01-29 19:52:56 +00:00
|
|
|
|
2018-01-30 19:48:26 +00:00
|
|
|
import styles from './styles';
|
|
|
|
import CustomEmoji from './CustomEmoji';
|
2018-02-08 14:08:50 +00:00
|
|
|
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
2019-01-29 19:52:56 +00:00
|
|
|
import { isIOS } from '../../utils/deviceInfo';
|
2018-01-30 19:48:26 +00:00
|
|
|
|
2019-01-29 19:52:56 +00:00
|
|
|
const EMOJIS_PER_ROW = isIOS ? 8 : 9;
|
2018-01-30 19:48:26 +00:00
|
|
|
|
2018-09-11 16:32:52 +00:00
|
|
|
const renderEmoji = (emoji, size, baseUrl) => {
|
2018-01-30 19:48:26 +00:00
|
|
|
if (emoji.isCustom) {
|
2018-09-11 16:32:52 +00:00
|
|
|
return <CustomEmoji style={[styles.customCategoryEmoji, { height: size - 8, width: size - 8 }]} emoji={emoji} baseUrl={baseUrl} />;
|
2018-01-30 19:48:26 +00:00
|
|
|
}
|
|
|
|
return (
|
|
|
|
<Text style={[styles.categoryEmoji, { height: size, width: size, fontSize: size - 14 }]}>
|
2019-09-16 20:50:51 +00:00
|
|
|
{shortnameToUnicode(`:${ emoji }:`)}
|
2018-01-30 19:48:26 +00:00
|
|
|
</Text>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2019-08-07 13:51:34 +00:00
|
|
|
class EmojiCategory extends React.Component {
|
2018-01-30 19:48:26 +00:00
|
|
|
static propTypes = {
|
2018-09-11 16:32:52 +00:00
|
|
|
baseUrl: PropTypes.string.isRequired,
|
2018-01-30 19:48:26 +00:00
|
|
|
emojis: PropTypes.any,
|
|
|
|
window: PropTypes.any,
|
|
|
|
onEmojiSelected: PropTypes.func,
|
|
|
|
emojisPerRow: PropTypes.number,
|
|
|
|
width: PropTypes.number
|
2018-09-25 19:28:42 +00:00
|
|
|
}
|
|
|
|
|
2018-01-30 19:48:26 +00:00
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
2018-09-25 19:28:42 +00:00
|
|
|
const { window, width, emojisPerRow } = this.props;
|
|
|
|
const { width: widthWidth, height: windowHeight } = window;
|
2018-01-30 19:48:26 +00:00
|
|
|
|
2018-09-25 19:28:42 +00:00
|
|
|
this.size = Math.min(width || widthWidth, windowHeight) / (emojisPerRow || EMOJIS_PER_ROW);
|
2018-03-06 17:40:44 +00:00
|
|
|
this.emojis = props.emojis;
|
2018-01-30 19:48:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
shouldComponentUpdate() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
renderItem(emoji, size) {
|
2018-09-25 19:28:42 +00:00
|
|
|
const { baseUrl, onEmojiSelected } = this.props;
|
2018-01-30 19:48:26 +00:00
|
|
|
return (
|
|
|
|
<TouchableOpacity
|
|
|
|
activeOpacity={0.7}
|
|
|
|
key={emoji.isCustom ? emoji.content : emoji}
|
2018-09-25 19:28:42 +00:00
|
|
|
onPress={() => onEmojiSelected(emoji)}
|
2018-05-23 13:39:18 +00:00
|
|
|
testID={`reaction-picker-${ emoji.isCustom ? emoji.content : emoji }`}
|
2018-01-30 19:48:26 +00:00
|
|
|
>
|
2018-09-11 16:32:52 +00:00
|
|
|
{renderEmoji(emoji, size, baseUrl)}
|
2019-02-07 15:48:10 +00:00
|
|
|
</TouchableOpacity>
|
|
|
|
);
|
2018-01-30 19:48:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
2018-09-25 19:28:42 +00:00
|
|
|
const { emojis } = this.props;
|
|
|
|
|
2018-02-08 14:08:50 +00:00
|
|
|
return (
|
|
|
|
<OptimizedFlatList
|
|
|
|
keyExtractor={item => (item.isCustom && item.content) || item}
|
2018-09-25 19:28:42 +00:00
|
|
|
data={emojis}
|
2018-02-08 14:08:50 +00:00
|
|
|
renderItem={({ item }) => this.renderItem(item, this.size)}
|
2018-09-25 19:28:42 +00:00
|
|
|
numColumns={EMOJIS_PER_ROW}
|
2018-02-08 14:08:50 +00:00
|
|
|
initialNumToRender={45}
|
|
|
|
getItemLayout={(data, index) => ({ length: this.size, offset: this.size * index, index })}
|
|
|
|
removeClippedSubviews
|
|
|
|
{...scrollPersistTaps}
|
|
|
|
/>
|
|
|
|
);
|
2018-01-30 19:48:26 +00:00
|
|
|
}
|
|
|
|
}
|
2019-08-07 13:51:34 +00:00
|
|
|
|
|
|
|
export default responsive(EmojiCategory);
|