forked from Ivasoft/mattermost-mobile
Do not cover empty search results on Emoji picker (#6402)
This commit is contained in:
@@ -3,24 +3,34 @@
|
||||
|
||||
import Fuse from 'fuse.js';
|
||||
import React, {useCallback, useMemo} from 'react';
|
||||
import {FlatList} from 'react-native';
|
||||
import {FlatList, StyleSheet, View} from 'react-native';
|
||||
|
||||
import NoResultsWithTerm from '@components/no_results_with_term';
|
||||
import {getEmojis, searchEmojis} from '@utils/emoji/helpers';
|
||||
|
||||
import EmojiItem from './emoji_item';
|
||||
import NoResults from './no_results';
|
||||
|
||||
import type CustomEmojiModel from '@typings/database/models/servers/custom_emoji';
|
||||
|
||||
type Props = {
|
||||
customEmojis: CustomEmojiModel[];
|
||||
keyboardHeight: number;
|
||||
skinTone: string;
|
||||
searchTerm: string;
|
||||
onEmojiPress: (emojiName: string) => void;
|
||||
};
|
||||
|
||||
const EmojiFiltered = ({customEmojis, skinTone, searchTerm, onEmojiPress}: Props) => {
|
||||
const style = StyleSheet.create({
|
||||
noResultContainer: {
|
||||
flexGrow: 1,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
});
|
||||
|
||||
const EmojiFiltered = ({customEmojis, keyboardHeight, skinTone, searchTerm, onEmojiPress}: Props) => {
|
||||
const emojis = useMemo(() => getEmojis(skinTone, customEmojis), [skinTone, customEmojis]);
|
||||
const flatListStyle = useMemo(() => ({flexGrow: 1, paddingBottom: keyboardHeight}), [keyboardHeight]);
|
||||
|
||||
const fuse = useMemo(() => {
|
||||
const options = {findAllMatches: true, ignoreLocation: true, includeMatches: true, shouldSort: false, includeScore: true};
|
||||
@@ -37,6 +47,14 @@ const EmojiFiltered = ({customEmojis, skinTone, searchTerm, onEmojiPress}: Props
|
||||
|
||||
const keyExtractor = useCallback((item) => item, []);
|
||||
|
||||
const renderEmpty = useCallback(() => {
|
||||
return (
|
||||
<View style={style.noResultContainer}>
|
||||
<NoResultsWithTerm term={searchTerm}/>
|
||||
</View>
|
||||
);
|
||||
}, [searchTerm]);
|
||||
|
||||
const renderItem = useCallback(({item}) => {
|
||||
return (
|
||||
<EmojiItem
|
||||
@@ -46,16 +64,15 @@ const EmojiFiltered = ({customEmojis, skinTone, searchTerm, onEmojiPress}: Props
|
||||
);
|
||||
}, []);
|
||||
|
||||
if (!data.length) {
|
||||
return <NoResults searchTerm={searchTerm}/>;
|
||||
}
|
||||
|
||||
return (
|
||||
<FlatList
|
||||
contentContainerStyle={flatListStyle}
|
||||
data={data}
|
||||
initialNumToRender={30}
|
||||
keyboardDismissMode='interactive'
|
||||
keyboardShouldPersistTaps='always'
|
||||
keyExtractor={keyExtractor}
|
||||
ListEmptyComponent={renderEmpty}
|
||||
renderItem={renderItem}
|
||||
removeClippedSubviews={false}
|
||||
/>
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
import {useIntl} from 'react-intl';
|
||||
import {Text, View} from 'react-native';
|
||||
|
||||
import CompassIcon from '@components/compass_icon';
|
||||
import {useTheme} from '@context/theme';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
|
||||
|
||||
type Props = {
|
||||
searchTerm: string;
|
||||
}
|
||||
|
||||
const getStyleSheetFromTheme = makeStyleSheetFromTheme((theme) => {
|
||||
return {
|
||||
flex: {
|
||||
flex: 1,
|
||||
},
|
||||
flexCenter: {
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
notFoundIcon: {
|
||||
backgroundColor: changeOpacity(theme.centerChannelColor, 0.04),
|
||||
width: 120,
|
||||
height: 120,
|
||||
borderRadius: 60,
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
notFoundText: {
|
||||
color: theme.centerChannelColor,
|
||||
marginTop: 16,
|
||||
},
|
||||
notFoundText20: {
|
||||
fontSize: 20,
|
||||
fontWeight: '600',
|
||||
},
|
||||
notFoundText15: {
|
||||
fontSize: 15,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
const NoResults = ({searchTerm}: Props) => {
|
||||
const theme = useTheme();
|
||||
const intl = useIntl();
|
||||
|
||||
const styles = getStyleSheetFromTheme(theme);
|
||||
const title = intl.formatMessage(
|
||||
{
|
||||
id: 'mobile.emoji_picker.search.not_found_title',
|
||||
defaultMessage: 'No results found for "{searchTerm}"',
|
||||
},
|
||||
{
|
||||
searchTerm,
|
||||
},
|
||||
);
|
||||
|
||||
const description = intl.formatMessage({
|
||||
id: 'mobile.emoji_picker.search.not_found_description',
|
||||
defaultMessage: 'Check the spelling or try another search.',
|
||||
});
|
||||
|
||||
return (
|
||||
<View style={[styles.flex, styles.flexCenter]}>
|
||||
<View style={styles.flexCenter}>
|
||||
<View style={styles.notFoundIcon}>
|
||||
<CompassIcon
|
||||
name='magnify'
|
||||
size={72}
|
||||
color={theme.buttonBg}
|
||||
/>
|
||||
</View>
|
||||
<Text style={[styles.notFoundText, styles.notFoundText20]}>
|
||||
{title}
|
||||
</Text>
|
||||
<Text style={[styles.notFoundText, styles.notFoundText15]}>
|
||||
{description}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default NoResults;
|
||||
@@ -15,6 +15,7 @@ import {Preferences} from '@constants';
|
||||
import {useServerUrl} from '@context/server';
|
||||
import {useTheme} from '@context/theme';
|
||||
import {debounce} from '@helpers/api/general';
|
||||
import {useKeyboardHeight} from '@hooks/device';
|
||||
import {queryAllCustomEmojis} from '@queries/servers/custom_emoji';
|
||||
import {queryPreferencesByCategoryAndName} from '@queries/servers/preference';
|
||||
import {observeConfigBooleanValue, observeRecentReactions} from '@queries/servers/system';
|
||||
@@ -56,6 +57,7 @@ type Props = {
|
||||
const EmojiPicker = ({customEmojis, customEmojisEnabled, onEmojiPress, recentEmojis, skinTone, testID = ''}: Props) => {
|
||||
const theme = useTheme();
|
||||
const serverUrl = useServerUrl();
|
||||
const keyboardHeight = useKeyboardHeight();
|
||||
const [width, setWidth] = useState(0);
|
||||
const [searchTerm, setSearchTerm] = useState<string|undefined>();
|
||||
const onLayout = useCallback(({nativeEvent}: LayoutChangeEvent) => setWidth(nativeEvent.layout.width), []);
|
||||
@@ -75,6 +77,7 @@ const EmojiPicker = ({customEmojis, customEmojisEnabled, onEmojiPress, recentEmo
|
||||
EmojiList = (
|
||||
<EmojiFiltered
|
||||
customEmojis={customEmojis}
|
||||
keyboardHeight={keyboardHeight}
|
||||
skinTone={skinTone}
|
||||
searchTerm={searchTerm}
|
||||
onEmojiPress={onEmojiPress}
|
||||
|
||||
@@ -120,7 +120,7 @@ const Reactions = ({currentUserId, canAddReaction, canRemoveReaction, disabled,
|
||||
onEmojiPress: handleAddReactionToPost,
|
||||
};
|
||||
|
||||
showModal(Screens.EMOJI_PICKER, title, passProps);
|
||||
showModal(Screens.EMOJI_PICKER, title, passProps, {modal: {swipeToDismiss: false}});
|
||||
}), [intl, theme]);
|
||||
|
||||
const handleReactionPress = useCallback(async (emoji: string, remove: boolean) => {
|
||||
|
||||
@@ -284,7 +284,7 @@ class CustomStatusModal extends NavigationComponent<Props, State> {
|
||||
const title = intl.formatMessage({id: 'mobile.custom_status.choose_emoji', defaultMessage: 'Choose an emoji'});
|
||||
const passProps = {closeButton: source, onEmojiPress: this.handleEmojiClick};
|
||||
|
||||
showModal(screen, title, passProps);
|
||||
showModal(screen, title, passProps, {modal: {swipeToDismiss: false}});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ const ReactionBar = ({recentEmojis = [], postId}: QuickReactionProps) => {
|
||||
const title = intl.formatMessage({id: 'mobile.post_info.add_reaction', defaultMessage: 'Add Reaction'});
|
||||
const passProps = {closeButton, onEmojiPress: handleEmojiPress};
|
||||
|
||||
showModal(screen, title, passProps);
|
||||
showModal(screen, title, passProps, {modal: {swipeToDismiss: false}});
|
||||
}, [intl, theme]);
|
||||
|
||||
let containerSize = LARGE_CONTAINER_SIZE;
|
||||
|
||||
Reference in New Issue
Block a user