[MM-26077] Emoji autocomplete fixes (#4512)

* Use 0 height over null and move fuse

* Deconstruct props

* Update app/components/autocomplete/emoji_suggestion/emoji_suggestion.js

Co-authored-by: Elias Nahum <nahumhbl@gmail.com>

* Update app/components/autocomplete/emoji_suggestion/emoji_suggestion.js

* Update snapshot

Co-authored-by: Elias Nahum <nahumhbl@gmail.com>
This commit is contained in:
Miguel Alatzar 2020-07-02 10:24:19 -07:00 committed by GitHub
parent 92e7adc852
commit 2ccf2dc716
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 73 additions and 34 deletions

View file

@ -1,6 +1,45 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`components/autocomplete/emoji_suggestion should match snapshot 1`] = `null`;
exports[`components/autocomplete/emoji_suggestion should match snapshot 1`] = `
<FlatList
ItemSeparatorComponent={[Function]}
data={Array []}
disableVirtualization={false}
extraData={
Object {
"active": false,
"dataSource": Array [],
}
}
horizontal={false}
initialListSize={10}
initialNumToRender={10}
keyExtractor={[Function]}
keyboardShouldPersistTaps="always"
maxToRenderPerBatch={10}
nestedScrollEnabled={false}
numColumns={1}
onEndReachedThreshold={2}
pageSize={10}
removeClippedSubviews={false}
renderItem={[Function]}
scrollEventThrottle={50}
style={
Array [
Object {
"backgroundColor": "#ffffff",
"flex": 1,
},
Object {
"height": 0,
"maxHeight": undefined,
},
]
}
updateCellsBatchingPeriod={50}
windowSize={21}
/>
`;
exports[`components/autocomplete/emoji_suggestion should match snapshot 2`] = `
<FlatList
@ -3047,6 +3086,7 @@ exports[`components/autocomplete/emoji_suggestion should match snapshot 2`] = `
"flex": 1,
},
Object {
"height": undefined,
"maxHeight": undefined,
},
]

View file

@ -9,6 +9,7 @@ import {
Text,
View,
} from 'react-native';
import Fuse from 'fuse.js';
import AutocompleteDivider from '@components/autocomplete/autocomplete_divider';
import Emoji from '@components/emoji';
@ -19,6 +20,16 @@ import {makeStyleSheetFromTheme} from '@utils/theme';
const EMOJI_REGEX = /(^|\s|^\+|^-)(:([^:\s]*))$/i;
const EMOJI_REGEX_WITHOUT_PREFIX = /\B(:([^:\s]*))$/i;
const FUSE_OPTIONS = {
shouldSort: false,
threshold: 0.3,
location: 0,
distance: 10,
includeMatches: true,
findAllMatches: true,
};
let fuse;
export default class EmojiSuggestion extends PureComponent {
static propTypes = {
@ -29,7 +40,6 @@ export default class EmojiSuggestion extends PureComponent {
cursorPosition: PropTypes.number,
customEmojisEnabled: PropTypes.bool,
emojis: PropTypes.array.isRequired,
fuse: PropTypes.object.isRequired,
isSearch: PropTypes.bool,
maxListHeight: PropTypes.number,
theme: PropTypes.object.isRequired,
@ -43,6 +53,7 @@ export default class EmojiSuggestion extends PureComponent {
static defaultProps = {
defaultChannel: {},
value: '',
emojis: [],
};
state = {
@ -54,14 +65,21 @@ export default class EmojiSuggestion extends PureComponent {
super(props);
this.matchTerm = '';
this.listRef = React.createRef();
fuse = new Fuse(props.emojis, FUSE_OPTIONS);
}
componentDidUpdate() {
if (this.props.isSearch) {
componentDidUpdate(prevProps) {
const {isSearch, emojis, cursorPosition, value} = this.props;
if (isSearch) {
return;
}
const {cursorPosition, value} = this.props;
if (emojis.join('') !== prevProps.emojis.join('')) {
fuse = new Fuse(emojis, FUSE_OPTIONS);
}
const match = value.substring(0, cursorPosition).match(EMOJI_REGEX);
if (!match || this.state.emojiComplete) {
@ -162,7 +180,7 @@ export default class EmojiSuggestion extends PureComponent {
}
searchEmojis = (searchTerm) => {
const {emojis, fuse} = this.props;
const {emojis} = this.props;
let sorter = compareEmojis;
if (searchTerm.trim().length) {
@ -198,18 +216,23 @@ export default class EmojiSuggestion extends PureComponent {
render() {
const {maxListHeight, theme, nestedScrollEnabled} = this.props;
let height;
if (!this.state.active) {
// If we are not in an active state return null so nothing is rendered
// other components are not blocked.
return null;
// If we are not in an active state set a height of 0 so nothing is rendered
// and other components are not blocked.
height = 0;
if (this.listRef.current) {
this.listRef.current.scrollToOffset({offset: 0});
}
}
const style = getStyleFromTheme(theme);
return (
<FlatList
ref={this.listRef}
keyboardShouldPersistTaps='always'
style={[style.listView, {maxHeight: maxListHeight}]}
style={[style.listView, {maxHeight: maxListHeight, height}]}
extraData={this.state}
data={this.state.dataSource}
keyExtractor={this.keyExtractor}

View file

@ -2,7 +2,6 @@
// See LICENSE.txt for license information.
import React from 'react';
import Fuse from 'fuse.js';
import Preferences from '@mm-redux/constants/preferences';
import {selectEmojisByName} from '@selectors/emojis';
@ -21,15 +20,6 @@ describe('components/autocomplete/emoji_suggestion', () => {
},
};
const emojis = selectEmojisByName(state);
const options = {
shouldSort: false,
threshold: 0.3,
location: 0,
distance: 10,
includeMatches: true,
findAllMatches: true,
};
const fuse = new Fuse(emojis, options);
const baseProps = {
actions: {
addReactionToLatestPost: jest.fn(),
@ -38,7 +28,6 @@ describe('components/autocomplete/emoji_suggestion', () => {
cursorPosition: 0,
customEmojisEnabled: false,
emojis,
fuse,
isSearch: false,
theme: Preferences.THEMES.default,
onChangeText: jest.fn(),

View file

@ -3,7 +3,6 @@
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import Fuse from 'fuse.js';
import {addReactionToLatestPost} from '@actions/views/emoji';
import {autocompleteCustomEmojis} from '@mm-redux/actions/emojis';
@ -15,20 +14,8 @@ import EmojiSuggestion from './emoji_suggestion';
function mapStateToProps(state) {
const emojis = selectEmojisByName(state);
const options = {
shouldSort: false,
threshold: 0.3,
location: 0,
distance: 10,
includeMatches: true,
findAllMatches: true,
};
const list = emojis.length ? emojis : [];
const fuse = new Fuse(list, options);
return {
fuse,
emojis,
customEmojisEnabled: getConfig(state).EnableCustomEmoji === 'true',
theme: getTheme(state),