MM-18453 Use native emojis (#3260)
* MM-18453 Use native emojis * Remove unnecessary else statement * Add support for builtIn emojis * Fix Native emojis snapshot tests * Set emoji text style from StyleSheet * Remove unneded version check and try/catch * Add builtIn emojis as custom emojis in emojiPicker * Simplify emojiPicker lists and fix jumping section headers * Update snapshots
This commit is contained in:
parent
218e104010
commit
114a18c16d
12 changed files with 158 additions and 119 deletions
|
|
@ -15,6 +15,8 @@ import {isMinimumServerVersion} from 'mattermost-redux/utils/helpers';
|
|||
|
||||
import AutocompleteDivider from 'app/components/autocomplete/autocomplete_divider';
|
||||
import Emoji from 'app/components/emoji';
|
||||
import {BuiltInEmojis} from 'app/utils/emojis';
|
||||
import {getEmojiByName} from 'app/utils/emoji_utils';
|
||||
import {makeStyleSheetFromTheme} from 'app/utils/theme';
|
||||
|
||||
const EMOJI_REGEX = /(^|\s|^\+|^-)(:([^:\s]*))$/i;
|
||||
|
|
@ -138,10 +140,16 @@ export default class EmojiSuggestion extends Component {
|
|||
// We are going to set a double : on iOS to prevent the auto correct from taking over and replacing it
|
||||
// with the wrong value, this is a hack but I could not found another way to solve it
|
||||
let completedDraft;
|
||||
let prefix = ':';
|
||||
if (Platform.OS === 'ios') {
|
||||
completedDraft = emojiPart.replace(EMOJI_REGEX_WITHOUT_PREFIX, `::${emoji}: `);
|
||||
prefix = '::';
|
||||
}
|
||||
|
||||
const emojiData = getEmojiByName(emoji);
|
||||
if (emojiData?.filename && !BuiltInEmojis.includes(emojiData.filename)) {
|
||||
completedDraft = emojiPart.replace(EMOJI_REGEX_WITHOUT_PREFIX, String.fromCodePoint(parseInt(emojiData.filename, 16)));
|
||||
} else {
|
||||
completedDraft = emojiPart.replace(EMOJI_REGEX_WITHOUT_PREFIX, `:${emoji}: `);
|
||||
completedDraft = emojiPart.replace(EMOJI_REGEX_WITHOUT_PREFIX, `${prefix}${emoji}: `);
|
||||
}
|
||||
|
||||
if (value.length > cursorPosition) {
|
||||
|
|
@ -150,7 +158,7 @@ export default class EmojiSuggestion extends Component {
|
|||
|
||||
onChangeText(completedDraft);
|
||||
|
||||
if (Platform.OS === 'ios') {
|
||||
if (Platform.OS === 'ios' && (!emojiData?.filename || BuiltInEmojis.includes(emojiData?.filename))) {
|
||||
// This is the second part of the hack were we replace the double : with just one
|
||||
// after the auto correct vanished
|
||||
setTimeout(() => {
|
||||
|
|
@ -178,6 +186,7 @@ export default class EmojiSuggestion extends Component {
|
|||
<View style={style.emoji}>
|
||||
<Emoji
|
||||
emojiName={item}
|
||||
textStyle={style.emojiText}
|
||||
size={20}
|
||||
/>
|
||||
</View>
|
||||
|
|
@ -225,6 +234,10 @@ const getStyleFromTheme = makeStyleSheetFromTheme((theme) => {
|
|||
fontSize: 13,
|
||||
color: theme.centerChannelColor,
|
||||
},
|
||||
emojiText: {
|
||||
color: '#000',
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
listView: {
|
||||
flex: 1,
|
||||
backgroundColor: theme.centerChannelBg,
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ export default class Emoji extends React.PureComponent {
|
|||
literal: PropTypes.string,
|
||||
size: PropTypes.number,
|
||||
textStyle: CustomPropTypes.Style,
|
||||
unicode: PropTypes.string,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
|
|
@ -116,6 +117,19 @@ export default class Emoji extends React.PureComponent {
|
|||
// force a new image to be rendered when the size changes
|
||||
const key = Platform.OS === 'android' ? (height + '-' + width) : null;
|
||||
|
||||
if (this.props.unicode && !this.props.imageUrl) {
|
||||
const codeArray = this.props.unicode.split('-');
|
||||
const code = codeArray.reduce((acc, c) => {
|
||||
return acc + String.fromCodePoint(parseInt(c, 16));
|
||||
}, '');
|
||||
|
||||
return (
|
||||
<Text style={[this.props.textStyle, {fontSize: size}]}>
|
||||
{code}
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
|
||||
if (!imageUrl) {
|
||||
return (
|
||||
<Image
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import {getConfig} from 'mattermost-redux/selectors/entities/general';
|
|||
import {Client4} from 'mattermost-redux/client';
|
||||
import {isMinimumServerVersion} from 'mattermost-redux/utils/helpers';
|
||||
|
||||
import {EmojiIndicesByAlias, Emojis} from 'app/utils/emojis';
|
||||
import {BuiltInEmojis, EmojiIndicesByAlias, Emojis} from 'app/utils/emojis';
|
||||
|
||||
import Emoji from './emoji';
|
||||
|
||||
|
|
@ -19,11 +19,15 @@ function mapStateToProps(state, ownProps) {
|
|||
const customEmojis = getCustomEmojisByName(state);
|
||||
|
||||
let imageUrl = '';
|
||||
let unicode;
|
||||
let isCustomEmoji = false;
|
||||
let displayTextOnly = false;
|
||||
if (EmojiIndicesByAlias.has(emojiName)) {
|
||||
if (EmojiIndicesByAlias.has(emojiName) || BuiltInEmojis.includes(emojiName)) {
|
||||
const emoji = Emojis[EmojiIndicesByAlias.get(emojiName)];
|
||||
imageUrl = Client4.getSystemEmojiImageUrl(emoji.filename);
|
||||
unicode = emoji.filename;
|
||||
if (BuiltInEmojis.includes(emojiName)) {
|
||||
imageUrl = Client4.getSystemEmojiImageUrl(emoji.filename);
|
||||
}
|
||||
} else if (customEmojis.has(emojiName)) {
|
||||
const emoji = customEmojis.get(emojiName);
|
||||
imageUrl = Client4.getCustomEmojiImageUrl(emoji.id);
|
||||
|
|
@ -33,7 +37,6 @@ function mapStateToProps(state, ownProps) {
|
|||
config.EnableCustomEmoji !== 'true' ||
|
||||
config.ExperimentalEnablePostMetadata === 'true' ||
|
||||
getCurrentUserId(state) === '' ||
|
||||
!isMinimumServerVersion(Client4.getServerVersion(), 4, 7) ||
|
||||
isMinimumServerVersion(Client4.getServerVersion(), 5, 12);
|
||||
}
|
||||
|
||||
|
|
@ -41,6 +44,7 @@ function mapStateToProps(state, ownProps) {
|
|||
imageUrl,
|
||||
isCustomEmoji,
|
||||
displayTextOnly,
|
||||
unicode,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ exports[`components/emoji_picker/EmojiPicker should match snapshot 1`] = `
|
|||
disableVirtualization={false}
|
||||
getItemLayout={[Function]}
|
||||
horizontal={false}
|
||||
initialNumToRender={10}
|
||||
initialNumToRender={50}
|
||||
keyExtractor={[Function]}
|
||||
keyboardDismissMode="interactive"
|
||||
keyboardShouldPersistTaps="always"
|
||||
|
|
@ -86,7 +86,7 @@ exports[`components/emoji_picker/EmojiPicker should match snapshot 1`] = `
|
|||
onMomentumScrollEnd={[Function]}
|
||||
onScroll={[Function]}
|
||||
onScrollToIndexFailed={[Function]}
|
||||
pageSize={30}
|
||||
pageSize={50}
|
||||
removeClippedSubviews={false}
|
||||
renderItem={[Function]}
|
||||
renderSectionHeader={[Function]}
|
||||
|
|
|
|||
|
|
@ -2,61 +2,20 @@
|
|||
// See LICENSE.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
import {
|
||||
FlatList,
|
||||
SectionList,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import {View} from 'react-native';
|
||||
|
||||
import SearchBar from 'app/components/search_bar';
|
||||
import {changeOpacity, getKeyboardAppearanceFromTheme} from 'app/utils/theme';
|
||||
|
||||
import EmojiPickerBase, {getStyleSheetFromTheme, SECTION_MARGIN} from './emoji_picker_base';
|
||||
import EmojiPickerBase, {getStyleSheetFromTheme} from './emoji_picker_base';
|
||||
|
||||
export default class EmojiPicker extends EmojiPickerBase {
|
||||
render() {
|
||||
const {formatMessage} = this.context.intl;
|
||||
const {deviceWidth, theme} = this.props;
|
||||
const {emojis, filteredEmojis, searchTerm} = this.state;
|
||||
const {theme} = this.props;
|
||||
const {searchTerm} = this.state;
|
||||
const styles = getStyleSheetFromTheme(theme);
|
||||
|
||||
let listComponent;
|
||||
if (searchTerm) {
|
||||
listComponent = (
|
||||
<FlatList
|
||||
keyboardShouldPersistTaps='always'
|
||||
style={styles.flatList}
|
||||
data={filteredEmojis}
|
||||
keyExtractor={this.flatListKeyExtractor}
|
||||
renderItem={this.flatListRenderItem}
|
||||
pageSize={10}
|
||||
initialListSize={10}
|
||||
removeClippedSubviews={true}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
listComponent = (
|
||||
<SectionList
|
||||
ref={this.attachSectionList}
|
||||
showsVerticalScrollIndicator={false}
|
||||
style={[styles.sectionList, {width: deviceWidth - (SECTION_MARGIN * 2)}]}
|
||||
sections={emojis}
|
||||
renderSectionHeader={this.renderSectionHeader}
|
||||
renderItem={this.renderItem}
|
||||
keyboardShouldPersistTaps='always'
|
||||
getItemLayout={this.sectionListGetItemLayout}
|
||||
removeClippedSubviews={true}
|
||||
onScroll={this.onScroll}
|
||||
onScrollToIndexFailed={this.handleScrollToSectionFailed}
|
||||
onMomentumScrollEnd={this.onMomentumScrollEnd}
|
||||
pageSize={30}
|
||||
ListFooterComponent={this.renderFooter}
|
||||
onEndReached={this.loadMoreCustomEmojis}
|
||||
onEndReachedThreshold={1}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const searchBarInput = {
|
||||
backgroundColor: theme.centerChannelBg,
|
||||
color: theme.centerChannelColor,
|
||||
|
|
@ -87,7 +46,7 @@ export default class EmojiPicker extends EmojiPickerBase {
|
|||
/>
|
||||
</View>
|
||||
<View style={styles.container}>
|
||||
{listComponent}
|
||||
{this.renderListComponent(2)}
|
||||
{!searchTerm &&
|
||||
<View style={styles.bottomContentWrapper}>
|
||||
<View style={styles.bottomContent}>
|
||||
|
|
|
|||
|
|
@ -3,9 +3,7 @@
|
|||
|
||||
import React from 'react';
|
||||
import {
|
||||
FlatList,
|
||||
KeyboardAvoidingView,
|
||||
SectionList,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import {KeyboardTrackingView} from 'react-native-keyboard-tracking-view';
|
||||
|
|
@ -16,58 +14,17 @@ import SearchBar from 'app/components/search_bar';
|
|||
import {DeviceTypes} from 'app/constants';
|
||||
import {changeOpacity, getKeyboardAppearanceFromTheme} from 'app/utils/theme';
|
||||
|
||||
import EmojiPickerBase, {getStyleSheetFromTheme, SECTION_MARGIN} from './emoji_picker_base';
|
||||
|
||||
const SCROLLVIEW_NATIVE_ID = 'emojiPicker';
|
||||
import EmojiPickerBase, {getStyleSheetFromTheme, SCROLLVIEW_NATIVE_ID} from './emoji_picker_base';
|
||||
|
||||
export default class EmojiPicker extends EmojiPickerBase {
|
||||
render() {
|
||||
const {formatMessage} = this.context.intl;
|
||||
const {deviceWidth, isLandscape, theme} = this.props;
|
||||
const {emojis, filteredEmojis, searchTerm} = this.state;
|
||||
const {isLandscape, theme} = this.props;
|
||||
const {searchTerm} = this.state;
|
||||
const styles = getStyleSheetFromTheme(theme);
|
||||
|
||||
const shorten = DeviceTypes.IS_IPHONE_WITH_INSETS && isLandscape ? 6 : 2;
|
||||
|
||||
let listComponent;
|
||||
if (searchTerm) {
|
||||
listComponent = (
|
||||
<FlatList
|
||||
data={filteredEmojis}
|
||||
initialListSize={10}
|
||||
keyboardShouldPersistTaps='always'
|
||||
keyExtractor={this.flatListKeyExtractor}
|
||||
nativeID={SCROLLVIEW_NATIVE_ID}
|
||||
pageSize={10}
|
||||
renderItem={this.flatListRenderItem}
|
||||
style={styles.flatList}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
listComponent = (
|
||||
<SectionList
|
||||
getItemLayout={this.sectionListGetItemLayout}
|
||||
keyboardShouldPersistTaps='always'
|
||||
keyboardDismissMode='interactive'
|
||||
ListFooterComponent={this.renderFooter}
|
||||
nativeID={SCROLLVIEW_NATIVE_ID}
|
||||
onEndReached={this.loadMoreCustomEmojis}
|
||||
onEndReachedThreshold={0}
|
||||
onMomentumScrollEnd={this.onMomentumScrollEnd}
|
||||
onScroll={this.onScroll}
|
||||
onScrollToIndexFailed={this.handleScrollToSectionFailed}
|
||||
pageSize={30}
|
||||
ref={this.attachSectionList}
|
||||
removeClippedSubviews={false}
|
||||
renderItem={this.renderItem}
|
||||
renderSectionHeader={this.renderSectionHeader}
|
||||
sections={emojis}
|
||||
showsVerticalScrollIndicator={false}
|
||||
style={[styles.sectionList, {width: deviceWidth - (SECTION_MARGIN * shorten)}]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
let keyboardOffset = DeviceTypes.IS_IPHONE_WITH_INSETS ? 50 : 30;
|
||||
if (isLandscape) {
|
||||
keyboardOffset = DeviceTypes.IS_IPHONE_WITH_INSETS ? 0 : 10;
|
||||
|
|
@ -111,7 +68,7 @@ export default class EmojiPicker extends EmojiPickerBase {
|
|||
/>
|
||||
</View>
|
||||
<View style={[styles.container]}>
|
||||
{listComponent}
|
||||
{this.renderListComponent(shorten)}
|
||||
{!searchTerm &&
|
||||
<KeyboardTrackingView
|
||||
ref={this.keyboardTracker}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@ import PropTypes from 'prop-types';
|
|||
import {intlShape} from 'react-intl';
|
||||
import {
|
||||
ActivityIndicator,
|
||||
FlatList,
|
||||
Platform,
|
||||
SectionList,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
|
|
@ -28,10 +30,11 @@ import {paddingHorizontal as padding} from 'app/components/safe_area_view/iphone
|
|||
import EmojiPickerRow from './emoji_picker_row';
|
||||
|
||||
const EMOJI_SIZE = 30;
|
||||
const EMOJI_GUTTER = 7.5;
|
||||
const EMOJI_GUTTER = 7;
|
||||
const EMOJIS_PER_PAGE = 200;
|
||||
const SECTION_HEADER_HEIGHT = 28;
|
||||
export const SECTION_MARGIN = 15;
|
||||
const SECTION_MARGIN = 15;
|
||||
export const SCROLLVIEW_NATIVE_ID = 'emojiPicker';
|
||||
|
||||
export function filterEmojiSearchInput(searchText) {
|
||||
return searchText.toLowerCase().replace(/^:|:$/g, '');
|
||||
|
|
@ -69,7 +72,7 @@ export default class EmojiPicker extends PureComponent {
|
|||
|
||||
this.sectionListGetItemLayout = sectionListGetItemLayout({
|
||||
getItemHeight: () => {
|
||||
return EMOJI_SIZE + (EMOJI_GUTTER * 2);
|
||||
return (EMOJI_SIZE + 5) + (EMOJI_GUTTER * 2);
|
||||
},
|
||||
getSectionHeaderHeight: () => SECTION_HEADER_HEIGHT,
|
||||
});
|
||||
|
|
@ -198,10 +201,6 @@ export default class EmojiPicker extends PureComponent {
|
|||
});
|
||||
};
|
||||
|
||||
filterEmojiAliases = (aliases, searchTerm) => {
|
||||
return aliases.findIndex((alias) => alias.includes(searchTerm)) !== -1;
|
||||
};
|
||||
|
||||
searchEmojis = (searchTerm) => {
|
||||
const {emojis, fuse} = this.props;
|
||||
const searchTermLowerCase = searchTerm.toLowerCase();
|
||||
|
|
@ -232,6 +231,54 @@ export default class EmojiPicker extends PureComponent {
|
|||
);
|
||||
};
|
||||
|
||||
renderListComponent = (shorten) => {
|
||||
const {deviceWidth, theme} = this.props;
|
||||
const {emojis, filteredEmojis, searchTerm} = this.state;
|
||||
const styles = getStyleSheetFromTheme(theme);
|
||||
|
||||
let listComponent;
|
||||
if (searchTerm) {
|
||||
listComponent = (
|
||||
<FlatList
|
||||
data={filteredEmojis}
|
||||
initialListSize={10}
|
||||
keyboardShouldPersistTaps='always'
|
||||
keyExtractor={this.flatListKeyExtractor}
|
||||
nativeID={SCROLLVIEW_NATIVE_ID}
|
||||
pageSize={10}
|
||||
renderItem={this.flatListRenderItem}
|
||||
style={styles.flatList}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
listComponent = (
|
||||
<SectionList
|
||||
getItemLayout={this.sectionListGetItemLayout}
|
||||
initialNumToRender={50}
|
||||
keyboardShouldPersistTaps='always'
|
||||
keyboardDismissMode='interactive'
|
||||
ListFooterComponent={this.renderFooter}
|
||||
nativeID={SCROLLVIEW_NATIVE_ID}
|
||||
onEndReached={this.loadMoreCustomEmojis}
|
||||
onEndReachedThreshold={Platform.OS === 'ios' ? 0 : 1}
|
||||
onMomentumScrollEnd={this.onMomentumScrollEnd}
|
||||
onScroll={this.onScroll}
|
||||
onScrollToIndexFailed={this.handleScrollToSectionFailed}
|
||||
pageSize={50}
|
||||
ref={this.attachSectionList}
|
||||
removeClippedSubviews={false}
|
||||
renderItem={this.renderItem}
|
||||
renderSectionHeader={this.renderSectionHeader}
|
||||
sections={emojis}
|
||||
showsVerticalScrollIndicator={false}
|
||||
style={[styles.sectionList, {width: deviceWidth - (SECTION_MARGIN * shorten)}]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return listComponent;
|
||||
};
|
||||
|
||||
flatListKeyExtractor = (item) => item;
|
||||
|
||||
flatListRenderItem = ({item}) => {
|
||||
|
|
@ -271,7 +318,7 @@ export default class EmojiPicker extends PureComponent {
|
|||
}
|
||||
|
||||
this.props.actions.incrementEmojiPickerPage();
|
||||
}
|
||||
};
|
||||
|
||||
onScroll = (e) => {
|
||||
if (this.state.jumpToSection) {
|
||||
|
|
@ -324,7 +371,7 @@ export default class EmojiPicker extends PureComponent {
|
|||
this.scrollToSection(index);
|
||||
}, 200);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
renderSectionHeader = ({section}) => {
|
||||
const {theme} = this.props;
|
||||
|
|
@ -351,7 +398,7 @@ export default class EmojiPicker extends PureComponent {
|
|||
if (isCustomSection && this.props.customEmojiPage === 0) {
|
||||
this.loadMoreCustomEmojis();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
renderSectionIcons = () => {
|
||||
const {theme} = this.props;
|
||||
|
|
@ -393,7 +440,7 @@ export default class EmojiPicker extends PureComponent {
|
|||
<ActivityIndicator/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export const getStyleSheetFromTheme = makeStyleSheetFromTheme((theme) => {
|
||||
|
|
|
|||
|
|
@ -27,11 +27,12 @@ export default class EmojiPickerRow extends Component {
|
|||
renderEmojis = (emoji, index, emojis) => {
|
||||
const {emojiGutter, emojiSize} = this.props;
|
||||
|
||||
const size = emojiSize + 5;
|
||||
const style = [
|
||||
styles.emoji,
|
||||
{
|
||||
width: emojiSize,
|
||||
height: emojiSize,
|
||||
width: size,
|
||||
height: size,
|
||||
marginHorizontal: emojiGutter,
|
||||
},
|
||||
];
|
||||
|
|
@ -60,6 +61,7 @@ export default class EmojiPickerRow extends Component {
|
|||
>
|
||||
<Emoji
|
||||
emojiName={emoji.name}
|
||||
textStyle={styles.emojiText}
|
||||
size={emojiSize}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
|
|
@ -79,7 +81,7 @@ export default class EmojiPickerRow extends Component {
|
|||
|
||||
const styles = StyleSheet.create({
|
||||
columnStyle: {
|
||||
alignSelf: 'stretch',
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
},
|
||||
|
|
@ -88,6 +90,10 @@ const styles = StyleSheet.create({
|
|||
justifyContent: 'center',
|
||||
overflow: 'hidden',
|
||||
},
|
||||
emojiText: {
|
||||
color: '#000',
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
emojiLeft: {
|
||||
marginLeft: 0,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import {getCustomEmojis, searchCustomEmojis} from 'mattermost-redux/actions/emoj
|
|||
|
||||
import {incrementEmojiPickerPage} from 'app/actions/views/emoji';
|
||||
import {getDimensions, isLandscape} from 'app/selectors/device';
|
||||
import {CategoryNames, Emojis, EmojiIndicesByAlias, EmojiIndicesByCategory} from 'app/utils/emojis';
|
||||
import {BuiltInEmojis, CategoryNames, Emojis, EmojiIndicesByAlias, EmojiIndicesByCategory} from 'app/utils/emojis';
|
||||
import {t} from 'app/utils/i18n';
|
||||
|
||||
import EmojiPicker from './emoji_picker';
|
||||
|
|
@ -96,6 +96,11 @@ const getEmojisBySection = createSelector(
|
|||
});
|
||||
|
||||
const customEmojiItems = [];
|
||||
BuiltInEmojis.forEach((emoji) => {
|
||||
customEmojiItems.push({
|
||||
name: emoji,
|
||||
});
|
||||
});
|
||||
|
||||
for (const [key] of customEmojis) {
|
||||
customEmojiItems.push({
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
import React, {PureComponent} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
Platform,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
} from 'react-native';
|
||||
|
|
@ -46,6 +47,7 @@ export default class Reaction extends PureComponent {
|
|||
<Emoji
|
||||
emojiName={emojiName}
|
||||
size={20}
|
||||
textStyle={{color: 'black', fontWeight: 'bold'}}
|
||||
padding={5}
|
||||
/>
|
||||
<Text style={styles.count}>{count}</Text>
|
||||
|
|
@ -73,8 +75,12 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
|||
marginRight: 6,
|
||||
marginBottom: 5,
|
||||
marginTop: 10,
|
||||
paddingVertical: 2,
|
||||
paddingHorizontal: 6,
|
||||
...Platform.select({
|
||||
android: {
|
||||
paddingBottom: 2,
|
||||
},
|
||||
}),
|
||||
},
|
||||
};
|
||||
});
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
import emojiRegex from 'emoji-regex';
|
||||
|
||||
import {EmojiIndicesByAlias} from './emojis';
|
||||
import {Emojis, EmojiIndicesByAlias} from './emojis';
|
||||
|
||||
const RE_NAMED_EMOJI = /(:([a-zA-Z0-9_-]+):)/g;
|
||||
|
||||
|
|
@ -105,3 +105,11 @@ export function doesMatchNamedEmoji(emojiName) {
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
export function getEmojiByName(emojiName) {
|
||||
if (EmojiIndicesByAlias.has(emojiName)) {
|
||||
return Emojis[EmojiIndicesByAlias.get(emojiName)];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue