From 3ee97881f35bbaf651e829a4b5b0c11886a43e7b Mon Sep 17 00:00:00 2001 From: Diego Mello Date: Fri, 27 Sep 2019 16:17:29 -0300 Subject: [PATCH] [FIX] Messagebox onChangeText issues (#1252) * Stop ongoing debounces on messagebox unmount * Immediately change send icon, but keep debouncing others * Make CustomEmoji stateless function * Fix mentions keyExtractor --- app/containers/EmojiPicker/CustomEmoji.js | 43 +++++++-------- app/containers/MessageBox/index.js | 65 ++++++++++++++++------- 2 files changed, 66 insertions(+), 42 deletions(-) diff --git a/app/containers/EmojiPicker/CustomEmoji.js b/app/containers/EmojiPicker/CustomEmoji.js index 03df9f61..381695d0 100644 --- a/app/containers/EmojiPicker/CustomEmoji.js +++ b/app/containers/EmojiPicker/CustomEmoji.js @@ -2,28 +2,25 @@ import React from 'react'; import FastImage from 'react-native-fast-image'; import PropTypes from 'prop-types'; -export default class CustomEmoji extends React.Component { - static propTypes = { - baseUrl: PropTypes.string.isRequired, - emoji: PropTypes.object.isRequired, - style: PropTypes.any - } +const CustomEmoji = React.memo(({ baseUrl, emoji, style }) => ( + +), (prevProps, nextProps) => { + const prevEmoji = prevProps.emoji.content || prevProps.emoji.name; + const nextEmoji = nextProps.emoji.content || nextProps.emoji.name; + return prevEmoji === nextEmoji; +}); - shouldComponentUpdate() { - return false; - } +CustomEmoji.propTypes = { + baseUrl: PropTypes.string.isRequired, + emoji: PropTypes.object.isRequired, + style: PropTypes.any +}; - render() { - const { baseUrl, emoji, style } = this.props; - return ( - - ); - } -} +export default CustomEmoji; diff --git a/app/containers/MessageBox/index.js b/app/containers/MessageBox/index.js index 9b66ac87..5abdcbf4 100644 --- a/app/containers/MessageBox/index.js +++ b/app/containers/MessageBox/index.js @@ -224,12 +224,34 @@ class MessageBox extends Component { componentWillUnmount() { console.countReset(`${ this.constructor.name }.render calls`); + if (this.onChangeText && this.onChangeText.stop) { + this.onChangeText.stop(); + } + if (this.getUsers && this.getUsers.stop) { + this.getUsers.stop(); + } + if (this.getRooms && this.getRooms.stop) { + this.getRooms.stop(); + } + if (this.getEmojis && this.getEmojis.stop) { + this.getEmojis.stop(); + } + if (this.getSlashCommands && this.getSlashCommands.stop) { + this.getSlashCommands.stop(); + } } - onChangeText = debounce(async(text) => { - const db = database.active; + onChangeText = (text) => { const isTextEmpty = text.length === 0; this.setShowSend(!isTextEmpty); + this.debouncedOnChangeText(text); + } + + // eslint-disable-next-line react/sort-comp + debouncedOnChangeText = debounce(async(text) => { + const db = database.active; + const isTextEmpty = text.length === 0; + // this.setShowSend(!isTextEmpty); this.handleTyping(!isTextEmpty); this.setInput(text); // matches if their is text that stats with '/' and group the command and params so we can use it "/command params" @@ -248,25 +270,29 @@ class MessageBox extends Component { } if (!isTextEmpty) { - const { start, end } = this.component._lastNativeSelection; - const cursor = Math.max(start, end); - const lastNativeText = this.component._lastNativeText; - // matches if text either starts with '/' or have (@,#,:) then it groups whatever comes next of mention type - const regexp = /(#|@|:|^\/)([a-z0-9._-]+)$/im; - const result = lastNativeText.substr(0, cursor).match(regexp); - if (!result) { - const slash = lastNativeText.match(/^\/$/); // matches only '/' in input - if (slash) { - return this.identifyMentionKeyword('', MENTIONS_TRACKING_TYPE_COMMANDS); + try { + const { start, end } = this.component._lastNativeSelection; + const cursor = Math.max(start, end); + const lastNativeText = this.component._lastNativeText || ''; + // matches if text either starts with '/' or have (@,#,:) then it groups whatever comes next of mention type + const regexp = /(#|@|:|^\/)([a-z0-9._-]+)$/im; + const result = lastNativeText.substr(0, cursor).match(regexp); + if (!result) { + const slash = lastNativeText.match(/^\/$/); // matches only '/' in input + if (slash) { + return this.identifyMentionKeyword('', MENTIONS_TRACKING_TYPE_COMMANDS); + } + return this.stopTrackingMention(); } - return this.stopTrackingMention(); + const [, lastChar, name] = result; + this.identifyMentionKeyword(name, lastChar); + } catch (e) { + log(e); } - const [, lastChar, name] = result; - this.identifyMentionKeyword(name, lastChar); } else { this.stopTrackingMention(); } - }, 100, true) + }, 100) onKeyboardResigned = () => { this.closeEmoji(); @@ -339,10 +365,10 @@ class MessageBox extends Component { getFixedMentions = (keyword) => { let result = []; if ('all'.indexOf(keyword) !== -1) { - result = [{ _id: -1, username: 'all' }]; + result = [{ id: -1, username: 'all' }]; } if ('here'.indexOf(keyword) !== -1) { - result = [{ _id: -2, username: 'here' }, ...result]; + result = [{ id: -2, username: 'here' }, ...result]; } return result; } @@ -813,8 +839,9 @@ class MessageBox extends Component { item._id || item.username || item.command || item} + keyExtractor={item => item.id || item.username || item.command || item} keyboardShouldPersistTaps='always' />