aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--package.json3
-rw-r--r--src/components/comments/AddComment.tsx83
-rw-r--r--src/components/common/TaggTypeahead.tsx37
3 files changed, 41 insertions, 82 deletions
diff --git a/package.json b/package.json
index b3d69c76..d3c02059 100644
--- a/package.json
+++ b/package.json
@@ -32,6 +32,7 @@
"react-native-animatable": "^1.3.3",
"react-native-confirmation-code-field": "^6.5.0",
"react-native-contacts": "^6.0.4",
+ "react-native-controlled-mentions": "^2.2.5",
"react-native-date-picker": "^3.2.5",
"react-native-device-info": "^7.3.1",
"react-native-document-picker": "^5.0.3",
@@ -102,4 +103,4 @@
"./node_modules/react-native-gesture-handler/jestSetup.js"
]
}
-}
+} \ No newline at end of file
diff --git a/src/components/comments/AddComment.tsx b/src/components/comments/AddComment.tsx
index 97c87299..7576675e 100644
--- a/src/components/comments/AddComment.tsx
+++ b/src/components/comments/AddComment.tsx
@@ -7,15 +7,14 @@ import {
TextInput,
View,
} from 'react-native';
+import {MentionInput} from 'react-native-controlled-mentions';
import {TouchableOpacity} from 'react-native-gesture-handler';
-import ParsedText, {ParseShape} from 'react-native-parsed-text';
import {useDispatch, useSelector} from 'react-redux';
import UpArrowIcon from '../../assets/icons/up_arrow.svg';
import {TAGG_LIGHT_BLUE} from '../../constants';
import {postComment} from '../../services';
import {updateReplyPosted} from '../../store/actions';
import {RootState} from '../../store/rootreducer';
-import {ProfilePreviewType} from '../../types';
import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils';
import {Avatar, TaggTypeahead} from '../common';
@@ -40,14 +39,9 @@ const AddComment: React.FC<AddCommentProps> = ({
}) => {
const [comment, setComment] = useState('');
const [keyboardVisible, setKeyboardVisible] = useState(false);
- const [isMentioning, setIsMentioning] = useState(false);
- const [mentionQuery, setMentionQuery] = useState('');
- const [selectedMention, setSelectedMention] = useState<ProfilePreviewType>();
- const [mentions, setMentions] = useState<ProfilePreviewType[]>([]);
const {avatar} = useSelector((state: RootState) => state.user);
const dispatch = useDispatch();
const ref = useRef<TextInput>(null);
- const [parsePatterns, setParsePatterns] = useState<ParseShape[]>([]);
const addComment = async () => {
const trimmed = comment.trim();
@@ -79,30 +73,6 @@ const AddComment: React.FC<AddCommentProps> = ({
};
useEffect(() => {
- setParsePatterns(
- mentions.map((m) => ({
- pattern: new RegExp(`@${m.username}`),
- style: {color: TAGG_LIGHT_BLUE},
- })),
- );
- }, [mentions]);
-
- useEffect(() => {
- if (selectedMention) {
- setComment(
- comment.replace(
- new RegExp(`@${mentionQuery}`),
- `@${selectedMention.username} `,
- ),
- );
- setMentions([...mentions, selectedMention]);
- setSelectedMention(undefined);
- setMentionQuery('');
- setIsMentioning(false);
- }
- }, [selectedMention]);
-
- useEffect(() => {
const showKeyboard = () => setKeyboardVisible(true);
Keyboard.addListener('keyboardWillShow', showKeyboard);
return () => Keyboard.removeListener('keyboardWillShow', showKeyboard);
@@ -125,12 +95,6 @@ const AddComment: React.FC<AddCommentProps> = ({
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
keyboardVerticalOffset={SCREEN_HEIGHT * 0.1}>
- {isMentioning && (
- <TaggTypeahead
- query={mentionQuery}
- setSelectedMention={setSelectedMention}
- />
- )}
<View
style={[
styles.container,
@@ -138,37 +102,22 @@ const AddComment: React.FC<AddCommentProps> = ({
]}>
<View style={styles.textContainer}>
<Avatar style={styles.avatar} uri={avatar} />
- <TextInput
- style={styles.text}
+ <MentionInput
+ containerStyle={styles.text}
placeholder={placeholderText}
- placeholderTextColor="grey"
- onChangeText={(newText: string) => {
- const newestChar = newText[newText.length - 1];
- const deletedChar =
- newText.length === comment.length - 1
- ? comment[comment.length - 1]
- : undefined;
- if (newestChar === ' ' || deletedChar === '@') {
- setIsMentioning(false);
- setMentionQuery('');
- }
- if (newestChar === '@') {
- setIsMentioning(true);
- }
- if (isMentioning) {
- const match = newText.match(/.*@(.*)$/);
- if (match) {
- setMentionQuery(match[1]);
- }
- }
- setComment(newText);
- }}
- multiline={true}
- ref={ref}>
- <ParsedText style={styles.text} parse={parsePatterns}>
- {comment}
- </ParsedText>
- </TextInput>
+ value={comment}
+ onChange={setComment}
+ inputRef={ref}
+ partTypes={[
+ {
+ trigger: '@',
+ renderSuggestions: (props) => <TaggTypeahead {...props} />,
+ allowedSpacesCount: 0,
+ isInsertSpaceAfterMention: true,
+ textStyle: {color: TAGG_LIGHT_BLUE},
+ },
+ ]}
+ />
<View style={styles.submitButton}>
<TouchableOpacity style={styles.submitButton} onPress={addComment}>
<UpArrowIcon width={35} height={35} color={'white'} />
diff --git a/src/components/common/TaggTypeahead.tsx b/src/components/common/TaggTypeahead.tsx
index 6239971e..7cd99278 100644
--- a/src/components/common/TaggTypeahead.tsx
+++ b/src/components/common/TaggTypeahead.tsx
@@ -1,33 +1,30 @@
import React, {Fragment, useEffect, useState} from 'react';
import {ScrollView, StyleSheet} from 'react-native';
+import {MentionSuggestionsProps} from 'react-native-controlled-mentions';
import {SEARCH_ENDPOINT_MESSAGES} from '../../constants';
import {loadSearchResults} from '../../services';
import {ProfilePreviewType} from '../../types';
import {SCREEN_WIDTH} from '../../utils';
import TaggUserRowCell from './TaggUserRowCell';
-type TaggTypeaheadProps = {
- query: string;
- setSelectedMention: (user: ProfilePreviewType) => void;
-};
-
-const TaggTypeahead: React.FC<TaggTypeaheadProps> = ({
- query,
- setSelectedMention,
+const TaggTypeahead: React.FC<MentionSuggestionsProps> = ({
+ keyword,
+ onSuggestionPress,
}) => {
const [results, setResults] = useState<ProfilePreviewType[]>([]);
+ const [height, setHeight] = useState(0);
useEffect(() => {
getQuerySuggested();
- }, [query]);
+ }, [keyword]);
const getQuerySuggested = async () => {
- if (query.length < 3) {
+ if (!keyword || keyword.length < 3) {
setResults([]);
return;
}
const searchResults = await loadSearchResults(
- `${SEARCH_ENDPOINT_MESSAGES}?query=${query}`,
+ `${SEARCH_ENDPOINT_MESSAGES}?query=${keyword}`,
);
if (searchResults && searchResults.users) {
setResults(searchResults.users);
@@ -39,11 +36,19 @@ const TaggTypeahead: React.FC<TaggTypeaheadProps> = ({
}
return (
- <ScrollView style={styles.container} showsVerticalScrollIndicator={false}>
+ <ScrollView
+ style={[styles.container, {top: -(height + 30)}]}
+ showsVerticalScrollIndicator={false}
+ onLayout={(event) => {
+ setHeight(event.nativeEvent.layout.height);
+ }}>
{results.map((user) => (
<TaggUserRowCell
onPress={() => {
- setSelectedMention(user);
+ onSuggestionPress({
+ id: user.id,
+ name: user.username,
+ });
setResults([]);
}}
user={user}
@@ -57,8 +62,12 @@ const styles = StyleSheet.create({
container: {
marginLeft: SCREEN_WIDTH * 0.05,
width: SCREEN_WIDTH * 0.9,
- maxHeight: 300,
+ maxHeight: 264,
borderRadius: 10,
+ backgroundColor: 'white',
+ position: 'absolute',
+ alignSelf: 'center',
+ zIndex: 1,
borderWidth: 1,
},
});