[IMPROVE] migrate the emoji component

This commit is contained in:
AlexAlexandre 2021-07-19 12:06:45 -03:00
parent 66a4627fec
commit f5eee1cbaf
6 changed files with 50 additions and 41 deletions

View File

@ -1,13 +1,10 @@
import React from 'react'; import React from 'react';
import FastImage from '@rocket.chat/react-native-fast-image'; import FastImage from '@rocket.chat/react-native-fast-image';
import {TEmoji} from "./index";
interface ICustomEmoji { interface ICustomEmoji {
baseUrl: string, baseUrl: string,
emoji: { emoji: TEmoji,
content: any;
name: string;
extension: any;
},
style: any style: any
} }

View File

@ -14,6 +14,8 @@ interface IEmoji {
onEmojiSelected({}: any): void; onEmojiSelected({}: any): void;
emojisPerRow: number; emojisPerRow: number;
width: number; width: number;
style: any;
tabLabel: string;
} }
const renderEmoji = (emoji: any, size: number, baseUrl: string) => { const renderEmoji = (emoji: any, size: number, baseUrl: string) => {
@ -27,7 +29,7 @@ const renderEmoji = (emoji: any, size: number, baseUrl: string) => {
); );
}; };
class EmojiCategory extends React.Component<IEmoji> { class EmojiCategory extends React.Component<Partial<IEmoji>> {
renderItem(emoji: any) { renderItem(emoji: any) {
const { baseUrl, onEmojiSelected } = this.props; const { baseUrl, onEmojiSelected } = this.props;
@ -35,10 +37,10 @@ class EmojiCategory extends React.Component<IEmoji> {
<TouchableOpacity <TouchableOpacity
activeOpacity={0.7} activeOpacity={0.7}
key={emoji && emoji.isCustom ? emoji.content : emoji} key={emoji && emoji.isCustom ? emoji.content : emoji}
onPress={() => onEmojiSelected(emoji)} onPress={() => onEmojiSelected!(emoji)}
testID={`reaction-picker-${ emoji && emoji.isCustom ? emoji.content : emoji }`} testID={`reaction-picker-${ emoji && emoji.isCustom ? emoji.content : emoji }`}
> >
{renderEmoji(emoji, EMOJI_SIZE, baseUrl)} {renderEmoji(emoji, EMOJI_SIZE, baseUrl!)}
</TouchableOpacity> </TouchableOpacity>
); );
} }

View File

@ -11,7 +11,7 @@ interface ITabBar {
theme: string theme: string
} }
export default class TabBar extends React.Component<ITabBar> { export default class TabBar extends React.Component<Partial<ITabBar>> {
shouldComponentUpdate(nextProps: any) { shouldComponentUpdate(nextProps: any) {
const { activeTab, theme } = this.props; const { activeTab, theme } = this.props;
@ -29,16 +29,16 @@ export default class TabBar extends React.Component<ITabBar> {
return ( return (
<View style={styles.tabsContainer}> <View style={styles.tabsContainer}>
{tabs.map((tab, i) => ( {tabs!.map((tab, i) => (
<TouchableOpacity <TouchableOpacity
activeOpacity={0.7} activeOpacity={0.7}
key={tab} key={tab}
onPress={() => goToPage(i)} onPress={() => goToPage!(i)}
style={styles.tab} style={styles.tab}
testID={`reaction-picker-${ tab }`} testID={`reaction-picker-${ tab }`}
> >
<Text style={[styles.tabEmoji, tabEmojiStyle]}>{tab}</Text> <Text style={[styles.tabEmoji, tabEmojiStyle]}>{tab}</Text>
{activeTab === i ? <View style={[styles.activeTabLine, { backgroundColor: themes[theme].tintColor }]} /> : <View style={styles.tabLine} />} {activeTab === i ? <View style={[styles.activeTabLine, { backgroundColor: themes[theme!].tintColor }]} /> : <View style={styles.tabLine} />}
</TouchableOpacity> </TouchableOpacity>
))} ))}
</View> </View>

View File

@ -1,6 +1,5 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { View } from 'react-native'; import { View } from 'react-native';
import PropTypes from 'prop-types';
import ScrollableTabView from 'react-native-scrollable-tab-view'; import ScrollableTabView from 'react-native-scrollable-tab-view';
import { dequal } from 'dequal'; import { dequal } from 'dequal';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
@ -18,22 +17,30 @@ import shortnameToUnicode from '../../utils/shortnameToUnicode';
import log from '../../utils/log'; import log from '../../utils/log';
import { themes } from '../../constants/colors'; import { themes } from '../../constants/colors';
import { withTheme } from '../../theme'; import { withTheme } from '../../theme';
import {IEmoji} from "../markdown/Emoji";
const scrollProps = { const scrollProps = {
keyboardShouldPersistTaps: 'always', keyboardShouldPersistTaps: 'always',
keyboardDismissMode: 'none' keyboardDismissMode: 'none'
}; };
class EmojiPicker extends Component { export type TEmoji = {
static propTypes = { content: any;
baseUrl: PropTypes.string.isRequired, name: string;
customEmojis: PropTypes.object, extension: any;
onEmojiSelected: PropTypes.func, isCustom: boolean;
tabEmojiStyle: PropTypes.object, }
theme: PropTypes.string
};
constructor(props) { interface IEmojiPickerState {
frequentlyUsed: [];
customEmojis: any;
show: boolean;
width: number | null;
}
class EmojiPicker extends Component<IEmoji, IEmojiPickerState> {
constructor(props: IEmoji) {
super(props); super(props);
const customEmojis = Object.keys(props.customEmojis) const customEmojis = Object.keys(props.customEmojis)
.filter(item => item === props.customEmojis[item].name) .filter(item => item === props.customEmojis[item].name)
@ -55,7 +62,7 @@ class EmojiPicker extends Component {
this.setState({ show: true }); this.setState({ show: true });
} }
shouldComponentUpdate(nextProps, nextState) { shouldComponentUpdate(nextProps: any, nextState: any) {
const { frequentlyUsed, show, width } = this.state; const { frequentlyUsed, show, width } = this.state;
const { theme } = this.props; const { theme } = this.props;
if (nextProps.theme !== theme) { if (nextProps.theme !== theme) {
@ -73,19 +80,19 @@ class EmojiPicker extends Component {
return false; return false;
} }
onEmojiSelected = (emoji) => { onEmojiSelected = (emoji: TEmoji) => {
try { try {
const { onEmojiSelected } = this.props; const { onEmojiSelected } = this.props;
if (emoji.isCustom) { if (emoji.isCustom) {
this._addFrequentlyUsed({ this._addFrequentlyUsed({
content: emoji.content, extension: emoji.extension, isCustom: true content: emoji.content, extension: emoji.extension, isCustom: true
}); });
onEmojiSelected(`:${ emoji.content }:`); onEmojiSelected!(`:${ emoji.content }:`);
} else { } else {
const content = emoji; const content = emoji;
this._addFrequentlyUsed({ content, isCustom: false }); this._addFrequentlyUsed({ content, isCustom: false });
const shortname = `:${ emoji }:`; const shortname = `:${ emoji }:`;
onEmojiSelected(shortnameToUnicode(shortname), shortname); onEmojiSelected!(shortnameToUnicode(shortname), shortname);
} }
} catch (e) { } catch (e) {
log(e); log(e);
@ -93,10 +100,10 @@ class EmojiPicker extends Component {
} }
// eslint-disable-next-line react/sort-comp // eslint-disable-next-line react/sort-comp
_addFrequentlyUsed = protectedFunction(async(emoji) => { _addFrequentlyUsed = protectedFunction(async(emoji: TEmoji) => {
const db = database.active; const db = database.active;
const freqEmojiCollection = db.get('frequently_used_emojis'); const freqEmojiCollection = db.get('frequently_used_emojis');
let freqEmojiRecord; let freqEmojiRecord: any;
try { try {
freqEmojiRecord = await freqEmojiCollection.find(emoji.content); freqEmojiRecord = await freqEmojiCollection.find(emoji.content);
} catch (error) { } catch (error) {
@ -105,11 +112,11 @@ class EmojiPicker extends Component {
await db.action(async() => { await db.action(async() => {
if (freqEmojiRecord) { if (freqEmojiRecord) {
await freqEmojiRecord.update((f) => { await freqEmojiRecord.update((f: any) => {
f.count += 1; f.count += 1;
}); });
} else { } else {
await freqEmojiCollection.create((f) => { await freqEmojiCollection.create((f: any) => {
f._raw = sanitizedRaw({ id: emoji.content }, freqEmojiCollection.schema); f._raw = sanitizedRaw({ id: emoji.content }, freqEmojiCollection.schema);
Object.assign(f, emoji); Object.assign(f, emoji);
f.count = 1; f.count = 1;
@ -121,8 +128,8 @@ class EmojiPicker extends Component {
updateFrequentlyUsed = async() => { updateFrequentlyUsed = async() => {
const db = database.active; const db = database.active;
const frequentlyUsedRecords = await db.get('frequently_used_emojis').query().fetch(); const frequentlyUsedRecords = await db.get('frequently_used_emojis').query().fetch();
let frequentlyUsed = orderBy(frequentlyUsedRecords, ['count'], ['desc']); let frequentlyUsed: any = orderBy(frequentlyUsedRecords, ['count'], ['desc']);
frequentlyUsed = frequentlyUsed.map((item) => { frequentlyUsed = frequentlyUsed.map((item: TEmoji) => {
if (item.isCustom) { if (item.isCustom) {
return { content: item.content, extension: item.extension, isCustom: item.isCustom }; return { content: item.content, extension: item.extension, isCustom: item.isCustom };
} }
@ -131,9 +138,9 @@ class EmojiPicker extends Component {
this.setState({ frequentlyUsed }); this.setState({ frequentlyUsed });
} }
onLayout = ({ nativeEvent: { layout: { width } } }) => this.setState({ width }); onLayout = ({ nativeEvent: { layout: { width } } }: any) => this.setState({ width });
renderCategory(category, i, label) { renderCategory(category: any, i: number, label: string) {
const { frequentlyUsed, customEmojis, width } = this.state; const { frequentlyUsed, customEmojis, width } = this.state;
const { baseUrl } = this.props; const { baseUrl } = this.props;
@ -150,7 +157,7 @@ class EmojiPicker extends Component {
emojis={emojis} emojis={emojis}
onEmojiSelected={emoji => this.onEmojiSelected(emoji)} onEmojiSelected={emoji => this.onEmojiSelected(emoji)}
style={styles.categoryContainer} style={styles.categoryContainer}
width={width} width={width!}
baseUrl={baseUrl} baseUrl={baseUrl}
tabLabel={label} tabLabel={label}
/> />
@ -168,8 +175,9 @@ class EmojiPicker extends Component {
<View onLayout={this.onLayout} style={{ flex: 1 }}> <View onLayout={this.onLayout} style={{ flex: 1 }}>
<ScrollableTabView <ScrollableTabView
renderTabBar={() => <TabBar tabEmojiStyle={tabEmojiStyle} theme={theme} />} renderTabBar={() => <TabBar tabEmojiStyle={tabEmojiStyle} theme={theme} />}
/*@ts-ignore*/
contentProps={scrollProps} contentProps={scrollProps}
style={{ backgroundColor: themes[theme].focusedBackground }} style={{ backgroundColor: themes[theme!].focusedBackground }}
> >
{ {
categories.tabs.map((tab, i) => ( categories.tabs.map((tab, i) => (
@ -184,7 +192,7 @@ class EmojiPicker extends Component {
} }
} }
const mapStateToProps = state => ({ const mapStateToProps = (state: IEmojiPickerState) => ({
customEmojis: state.customEmojis customEmojis: state.customEmojis
}); });

View File

@ -7,14 +7,16 @@ import { themes } from '../../constants/colors';
import styles from './styles'; import styles from './styles';
interface IEmoji { export interface IEmoji {
literal: string; literal: string;
isMessageContainsOnlyEmoji: boolean; isMessageContainsOnlyEmoji: boolean;
getCustomEmoji?({}: any): string; getCustomEmoji?: Function;
baseUrl: string; baseUrl: string;
customEmojis?: boolean; customEmojis?: any;
style: object; style: object;
theme?: string; theme?: string;
onEmojiSelected?: Function;
tabEmojiStyle?: object;
} }
const Emoji = React.memo(({ const Emoji = React.memo(({

View File

@ -1,4 +1,4 @@
export const emojisByCategory = { export const emojisByCategory: any = {
people: [ people: [
'grinning', 'grinning',
'grimacing', 'grimacing',