aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components/comments/AddComment.tsx118
-rw-r--r--src/components/comments/CommentTextField.tsx147
-rw-r--r--src/components/comments/MentionInputControlled.tsx55
-rw-r--r--src/components/comments/index.ts1
-rw-r--r--src/components/common/TaggTypeahead.tsx80
-rw-r--r--src/components/moments/MomentCommentPreview.tsx8
-rw-r--r--src/screens/profile/CaptionScreen.tsx6
-rw-r--r--src/utils/comments.tsx11
8 files changed, 306 insertions, 120 deletions
diff --git a/src/components/comments/AddComment.tsx b/src/components/comments/AddComment.tsx
index 9667046c..01325475 100644
--- a/src/components/comments/AddComment.tsx
+++ b/src/components/comments/AddComment.tsx
@@ -7,43 +7,29 @@ import {
TextInput,
View,
} from 'react-native';
-import {TouchableOpacity} from 'react-native-gesture-handler';
-import {useDispatch, useSelector} from 'react-redux';
-import UpArrowIcon from '../../assets/icons/up_arrow.svg';
+import {useDispatch} from 'react-redux';
import {TAGG_LIGHT_BLUE} from '../../constants';
import {CommentContext} from '../../screens/profile/MomentCommentsScreen';
import {postComment} from '../../services';
import {updateReplyPosted} from '../../store/actions';
-import {RootState} from '../../store/rootreducer';
import {CommentThreadType, CommentType} from '../../types';
import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils';
import {mentionPartTypes} from '../../utils/comments';
-import {Avatar} from '../common';
-import {MentionInputControlled} from './MentionInputControlled';
+import {CommentTextField} from './CommentTextField';
+import MentionInputControlled from './MentionInputControlled';
+import {normalize} from 'react-native-elements';
export interface AddCommentProps {
momentId: string;
placeholderText: string;
- callback?: (message: string) => void;
- onFocus?: () => void;
- isKeyboardAvoiding?: boolean;
- theme?: 'dark' | 'white';
}
-const AddComment: React.FC<AddCommentProps> = ({
- momentId,
- placeholderText,
- callback = (_) => null,
- onFocus = () => null,
- isKeyboardAvoiding = true,
- theme = 'white',
-}) => {
- const {setShouldUpdateAllComments = () => null, commentTapped} =
+const AddComment: React.FC<AddCommentProps> = ({momentId, placeholderText}) => {
+ const {setShouldUpdateAllComments, commentTapped} =
useContext(CommentContext);
const [inReplyToMention, setInReplyToMention] = useState('');
const [comment, setComment] = useState('');
const [keyboardVisible, setKeyboardVisible] = useState(false);
- const {avatar} = useSelector((state: RootState) => state.user);
const dispatch = useDispatch();
const ref = useRef<TextInput>(null);
const isReplyingToComment =
@@ -61,15 +47,13 @@ const AddComment: React.FC<AddCommentProps> = ({
if (trimmed === '') {
return;
}
- const message = inReplyToMention + trimmed;
const postedComment = await postComment(
- message,
+ inReplyToMention + trimmed,
objectId,
isReplyingToComment || isReplyingToReply,
);
if (postedComment) {
- callback(message);
setComment('');
setInReplyToMention('');
@@ -113,81 +97,64 @@ const AddComment: React.FC<AddCommentProps> = ({
}
}, [isReplyingToComment, isReplyingToReply, commentTapped]);
- const mainContent = () => (
- <View
- style={[
- theme === 'white' ? styles.containerWhite : styles.containerDark,
- keyboardVisible && theme !== 'dark' ? styles.whiteBackround : {},
- ]}>
- <View style={styles.textContainer}>
- <Avatar style={styles.avatar} uri={avatar} />
- <MentionInputControlled
- containerStyle={styles.text}
- placeholderTextColor={theme === 'dark' ? '#828282' : undefined}
- placeholder={placeholderText}
- value={inReplyToMention + comment}
- onFocus={onFocus}
- onChange={(newText: string) => {
- // skipping the `inReplyToMention` text
- setComment(
- newText.substring(inReplyToMention.length, newText.length),
- );
- }}
- inputRef={ref}
- partTypes={mentionPartTypes('blue')}
- />
- {(theme === 'white' || (theme === 'dark' && keyboardVisible)) && (
- <View style={styles.submitButton}>
- <TouchableOpacity
- style={
- comment === ''
- ? [styles.submitButton, styles.greyButton]
- : styles.submitButton
- }
- disabled={comment === ''}
- onPress={addComment}>
- <UpArrowIcon width={35} height={35} color={'white'} />
- </TouchableOpacity>
- </View>
- )}
- </View>
- </View>
- );
- return isKeyboardAvoiding ? (
+ return (
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
keyboardVerticalOffset={SCREEN_HEIGHT * 0.1}>
- {mainContent()}
+ <View
+ style={[
+ styles.container,
+ keyboardVisible ? styles.whiteBackround : {},
+ ]}>
+ <View style={styles.textContainer}>
+ <MentionInputControlled
+ containerStyle={styles.text}
+ placeholder={placeholderText}
+ value={inReplyToMention + comment}
+ onChange={(newText: string) => {
+ // skipping the `inReplyToMention` text
+ setComment(
+ newText.substring(inReplyToMention.length, newText.length),
+ );
+ }}
+ inputRef={ref}
+ partTypes={mentionPartTypes('blue', 'comment')}
+ addComment={addComment}
+ NewText={CommentTextField}
+ />
+ </View>
+ </View>
</KeyboardAvoidingView>
- ) : (
- mainContent()
);
};
const styles = StyleSheet.create({
- containerDark: {
- alignItems: 'center',
- width: SCREEN_WIDTH,
- },
- containerWhite: {
+ container: {
backgroundColor: '#f7f7f7',
alignItems: 'center',
+ justifyContent: 'center',
width: SCREEN_WIDTH,
},
textContainer: {
width: '95%',
- flexDirection: 'row',
+ // flexDirection: 'row',
backgroundColor: '#e8e8e8',
alignItems: 'center',
+ // alignSelf: 'center',
justifyContent: 'space-between',
+ // justifyContent: 'center',
margin: '3%',
borderRadius: 25,
+ // borderWidth: 1,
+ // flex: 1,
+ height: normalize(45),
},
text: {
flex: 1,
padding: '1%',
- marginHorizontal: '1%',
+ // marginHorizontal: '1%',
maxHeight: 100,
+ // borderWidth: 1,
},
avatar: {
height: 35,
@@ -209,9 +176,6 @@ const styles = StyleSheet.create({
marginVertical: '2%',
alignSelf: 'flex-end',
},
- greyButton: {
- backgroundColor: 'grey',
- },
whiteBackround: {
backgroundColor: '#fff',
},
diff --git a/src/components/comments/CommentTextField.tsx b/src/components/comments/CommentTextField.tsx
new file mode 100644
index 00000000..3e97449c
--- /dev/null
+++ b/src/components/comments/CommentTextField.tsx
@@ -0,0 +1,147 @@
+import React, {FC, ReactFragment} from 'react';
+import {
+ NativeSyntheticEvent,
+ StyleSheet,
+ StyleProp,
+ Text,
+ TextInput,
+ TextInputSelectionChangeEventData,
+ TouchableOpacity,
+ View,
+ ViewStyle,
+} from 'react-native';
+import {useSelector} from 'react-redux';
+import {TAGG_LIGHT_BLUE} from '../../constants';
+import {RootState} from '../../store/rootReducer';
+import {
+ Part,
+ PartType,
+ MentionPartType,
+} from 'react-native-controlled-mentions/dist/types';
+import {
+ defaultMentionTextStyle,
+ isMentionPartType,
+} from 'react-native-controlled-mentions/dist/utils';
+import {Avatar} from '../common';
+import {normalize} from 'react-native-elements';
+
+import UpArrowIcon from '../../assets/icons/up_arrow.svg';
+
+type CommentTextFieldProps = {
+ containerStyle: StyleProp<ViewStyle>;
+ validateInput: any;
+ keyboardText: string;
+ partTypes: PartType[];
+ renderMentionSuggestions: (mentionType: MentionPartType) => ReactFragment;
+ handleTextInputRef: (ref: TextInput) => null;
+ onChangeInput: (changedText: string) => null;
+ handleSelectionChange: (
+ event: NativeSyntheticEvent<TextInputSelectionChangeEventData>,
+ ) => null;
+ parts: Part[];
+ addComment: () => any;
+};
+
+const CommentTextField: FC<CommentTextFieldProps> = ({
+ containerStyle,
+ validateInput,
+ keyboardText,
+ partTypes,
+ renderMentionSuggestions,
+ handleTextInputRef,
+ onChangeInput,
+ handleSelectionChange,
+ parts,
+ addComment,
+ ...textInputProps
+}) => {
+ const {avatar} = useSelector((state: RootState) => state.user);
+
+ return (
+ <View style={containerStyle}>
+ {validateInput(keyboardText)
+ ? (
+ partTypes.filter(
+ (one) =>
+ isMentionPartType(one) &&
+ one.renderSuggestions != null &&
+ !one.isBottomMentionSuggestionsRender,
+ ) as MentionPartType[]
+ ).map(renderMentionSuggestions)
+ : null}
+
+ <View style={styles.containerStyle}>
+ <Avatar style={styles.avatar} uri={avatar} />
+ <TextInput
+ multiline
+ {...textInputProps}
+ ref={handleTextInputRef}
+ onChangeText={onChangeInput}
+ onSelectionChange={handleSelectionChange}
+ style={styles.text}>
+ <Text>
+ {parts.map(({text, partType, data}, index) =>
+ partType ? (
+ <Text
+ key={`${index}-${data?.trigger ?? 'pattern'}`}
+ style={partType.textStyle ?? defaultMentionTextStyle}>
+ {text}
+ </Text>
+ ) : (
+ <Text key={index}>{text}</Text>
+ ),
+ )}
+ </Text>
+ </TextInput>
+ <View style={styles.submitButton}>
+ <TouchableOpacity style={styles.submitButton} onPress={addComment}>
+ <UpArrowIcon width={35} height={35} color={'white'} />
+ </TouchableOpacity>
+ </View>
+ </View>
+
+ {validateInput(keyboardText)
+ ? (
+ partTypes.filter(
+ (one) =>
+ isMentionPartType(one) &&
+ one.renderSuggestions != null &&
+ one.isBottomMentionSuggestionsRender,
+ ) as MentionPartType[]
+ ).map(renderMentionSuggestions)
+ : null}
+ </View>
+ );
+};
+
+const styles = StyleSheet.create({
+ avatar: {
+ height: 35,
+ width: 35,
+ borderRadius: 30,
+ marginRight: 10,
+ marginLeft: '3%',
+ marginVertical: '2%',
+ },
+ containerStyle: {
+ flexDirection: 'row',
+ alignSelf: 'center',
+ alignItems: 'center',
+ justifyContent: 'center',
+ height: normalize(40),
+ },
+ submitButton: {
+ height: 35,
+ width: 35,
+ backgroundColor: TAGG_LIGHT_BLUE,
+ borderRadius: 999,
+ justifyContent: 'center',
+ alignItems: 'center',
+ marginRight: '3%',
+ marginVertical: '2%',
+ alignSelf: 'flex-end',
+ },
+ text: {flex: 1},
+});
+
+export {CommentTextField};
diff --git a/src/components/comments/MentionInputControlled.tsx b/src/components/comments/MentionInputControlled.tsx
index 2fd2b41d..de52d1c1 100644
--- a/src/components/comments/MentionInputControlled.tsx
+++ b/src/components/comments/MentionInputControlled.tsx
@@ -1,13 +1,23 @@
-import React, {FC, MutableRefObject, useMemo, useRef, useState} from 'react';
+import React, {
+ FC,
+ MutableRefObject,
+ Ref,
+ useMemo,
+ useRef,
+ useState,
+} from 'react';
import {
NativeSyntheticEvent,
+ StyleProp,
Text,
TextInput,
+ TextInputProps,
TextInputSelectionChangeEventData,
View,
+ ViewStyle,
} from 'react-native';
import {
- MentionInputProps,
+ PatternPartType,
MentionPartType,
Suggestion,
} from 'react-native-controlled-mentions/dist/types';
@@ -20,7 +30,24 @@ import {
parseValue,
} from 'react-native-controlled-mentions/dist/utils';
-const MentionInputControlled: FC<MentionInputProps> = ({
+type PartType = MentionPartType | PatternPartType;
+
+type MentionInputControlledProps = Omit<TextInputProps, 'onChange'> & {
+ value: string;
+ onChange: (value: string) => any;
+
+ partTypes?: PartType[];
+
+ inputRef?: Ref<TextInput>;
+
+ containerStyle?: StyleProp<ViewStyle>;
+
+ addComment?: () => any | null;
+
+ NewText?: FC<any>;
+};
+
+const MentionInputControlled: FC<MentionInputControlledProps> = ({
value,
onChange,
@@ -32,6 +59,10 @@ const MentionInputControlled: FC<MentionInputProps> = ({
onSelectionChange,
+ addComment,
+
+ NewText,
+
...textInputProps
}) => {
const textInput = useRef<TextInput | null>(null);
@@ -147,7 +178,21 @@ const MentionInputControlled: FC<MentionInputProps> = ({
return validRegex().test(testString);
};
- return (
+ return NewText ? (
+ <NewText
+ {...textInputProps}
+ containerStyle={containerStyle}
+ validateInput={validateInput}
+ keyboardText={keyboardText}
+ partTypes={partTypes}
+ renderMentionSuggestions={renderMentionSuggestions}
+ handleTextInputRef={handleTextInputRef}
+ onChangeInput={onChangeInput}
+ handleSelectionChange={handleSelectionChange}
+ parts={parts}
+ addComment={addComment}
+ />
+ ) : (
<View style={containerStyle}>
{validateInput(keyboardText)
? (
@@ -195,4 +240,4 @@ const MentionInputControlled: FC<MentionInputProps> = ({
);
};
-export {MentionInputControlled};
+export default MentionInputControlled;
diff --git a/src/components/comments/index.ts b/src/components/comments/index.ts
index ebd93844..77334cb3 100644
--- a/src/components/comments/index.ts
+++ b/src/components/comments/index.ts
@@ -1,2 +1,3 @@
export {default as CommentTile} from './CommentTile';
export {default as AddComment} from './AddComment';
+export {default as MentionInputControlled} from './MentionInputControlled';
diff --git a/src/components/common/TaggTypeahead.tsx b/src/components/common/TaggTypeahead.tsx
index 747e0bb5..6b3df559 100644
--- a/src/components/common/TaggTypeahead.tsx
+++ b/src/components/common/TaggTypeahead.tsx
@@ -1,21 +1,35 @@
import React, {Fragment, useEffect, useState} from 'react';
-import {ScrollView, StyleSheet} from 'react-native';
-import {MentionSuggestionsProps} from 'react-native-controlled-mentions';
+import {ScrollView, StyleSheet, View} from 'react-native';
+import {Suggestion} from 'react-native-controlled-mentions';
import {useSelector} from 'react-redux';
import {SEARCH_ENDPOINT_MESSAGES} from '../../constants';
import {loadSearchResults} from '../../services';
import {RootState} from '../../store/rootReducer';
import {ProfilePreviewType} from '../../types';
-import {SCREEN_WIDTH, shuffle} from '../../utils';
+import {SCREEN_HEIGHT, SCREEN_WIDTH, shuffle} from '../../utils';
import TaggUserRowCell from './TaggUserRowCell';
-const TaggTypeahead: React.FC<MentionSuggestionsProps> = ({
+type TaggTypeaheadProps = {
+ keyword: string | undefined;
+ component: string | undefined;
+ onSuggestionPress: (suggestion: Suggestion) => void;
+};
+
+const TaggTypeahead: React.FC<TaggTypeaheadProps> = ({
keyword,
+ component,
onSuggestionPress,
}) => {
const {friends} = useSelector((state: RootState) => state.friends);
const [results, setResults] = useState<ProfilePreviewType[]>([]);
const [height, setHeight] = useState(0);
+ const [margin, setMargin] = useState(0);
+
+ useEffect(() => {
+ if (component === 'comment') {
+ setMargin(-10);
+ }
+ }, [component]);
useEffect(() => {
if (keyword === '') {
@@ -42,40 +56,50 @@ const TaggTypeahead: React.FC<MentionSuggestionsProps> = ({
}
return (
- <ScrollView
- style={[styles.container, {top: -(height + 30)}]}
- showsVerticalScrollIndicator={false}
- onLayout={(event) => {
- setHeight(event.nativeEvent.layout.height);
- }}
- keyboardShouldPersistTaps={'always'}>
- {results.map((user) => (
- <TaggUserRowCell
- onPress={() => {
- setResults([]);
- onSuggestionPress({
- id: user.id,
- name: user.username,
- });
- }}
- user={user}
- />
- ))}
- </ScrollView>
+ <View>
+ <View style={styles.overlay} />
+ <ScrollView
+ style={[styles.container, {top: -height, margin: margin}]}
+ showsVerticalScrollIndicator={false}
+ onLayout={(event) => {
+ setHeight(event.nativeEvent.layout.height);
+ }}
+ keyboardShouldPersistTaps={'always'}>
+ {results.map((user) => (
+ <TaggUserRowCell
+ onPress={() => {
+ setResults([]);
+ onSuggestionPress({
+ id: user.id,
+ name: user.username,
+ });
+ }}
+ user={user}
+ />
+ ))}
+ </ScrollView>
+ </View>
);
};
const styles = StyleSheet.create({
container: {
- marginLeft: SCREEN_WIDTH * 0.05,
- width: SCREEN_WIDTH * 0.9,
+ width: SCREEN_WIDTH,
maxHeight: 264,
- borderRadius: 10,
backgroundColor: 'white',
position: 'absolute',
alignSelf: 'center',
zIndex: 1,
- borderWidth: 1,
+ },
+ overlay: {
+ width: SCREEN_WIDTH,
+ height: SCREEN_HEIGHT,
+ backgroundColor: 'gray',
+ opacity: 0.4,
+ position: 'absolute',
+ alignSelf: 'center',
+ bottom: 10,
+ zIndex: -1,
},
});
diff --git a/src/components/moments/MomentCommentPreview.tsx b/src/components/moments/MomentCommentPreview.tsx
index e53ed258..f6b9d75b 100644
--- a/src/components/moments/MomentCommentPreview.tsx
+++ b/src/components/moments/MomentCommentPreview.tsx
@@ -9,7 +9,7 @@ import {mentionPartTypes, renderTextWithMentions} from '../../utils/comments';
interface MomentCommentPreviewProps {
momentId: string;
- commentsCount: number;
+ commentsCount: number | null;
commentPreview: MomentCommentPreviewType | null;
screenType: ScreenType;
}
@@ -23,7 +23,9 @@ const MomentCommentPreview: React.FC<MomentCommentPreviewProps> = ({
const navigation = useNavigation();
const state = useStore().getState();
const commentCountText =
- commentsCount === 0 ? 'No Comments' : commentsCount + ' comments';
+ !commentsCount || commentsCount === 0
+ ? 'No Comments'
+ : commentsCount + ' comments';
return (
<TouchableOpacity
@@ -35,7 +37,7 @@ const MomentCommentPreview: React.FC<MomentCommentPreviewProps> = ({
})
}>
<Text style={styles.whiteBold}>{commentCountText}</Text>
- {commentPreview !== null && (
+ {commentPreview && (
<View style={styles.previewContainer}>
<Image
source={{
diff --git a/src/screens/profile/CaptionScreen.tsx b/src/screens/profile/CaptionScreen.tsx
index 9e1b4674..253346d5 100644
--- a/src/screens/profile/CaptionScreen.tsx
+++ b/src/screens/profile/CaptionScreen.tsx
@@ -13,7 +13,7 @@ import {
TouchableWithoutFeedback,
View,
} from 'react-native';
-import {MentionInput} from 'react-native-controlled-mentions';
+import {MentionInputControlled} from '../../components';
import {Button, normalize} from 'react-native-elements';
import {useDispatch, useSelector} from 'react-redux';
import FrontArrow from '../../assets/icons/front-arrow.svg';
@@ -199,13 +199,13 @@ const CaptionScreen: React.FC<CaptionScreenProps> = ({route, navigation}) => {
source={{uri: moment ? moment.moment_url : image?.path}}
resizeMode={'cover'}
/>
- <MentionInput
+ <MentionInputControlled
containerStyle={styles.text}
placeholder="Write something....."
placeholderTextColor="gray"
value={caption}
onChange={setCaption}
- partTypes={mentionPartTypes('blue')}
+ partTypes={mentionPartTypes('blue', 'caption')}
/>
<TouchableOpacity
onPress={() =>
diff --git a/src/utils/comments.tsx b/src/utils/comments.tsx
index 910b44e7..28879622 100644
--- a/src/utils/comments.tsx
+++ b/src/utils/comments.tsx
@@ -79,13 +79,16 @@ export const renderTextWithMentions: React.FC<RenderProps> = ({
);
};
-export const mentionPartTypes: (theme: 'blue' | 'white') => PartType[] = (
- theme,
-) => {
+export const mentionPartTypes: (
+ theme: 'blue' | 'white',
+ component: 'caption' | 'comment',
+) => PartType[] = (theme, component) => {
return [
{
trigger: '@',
- renderSuggestions: (props) => <TaggTypeahead {...props} />,
+ renderSuggestions: (props) => (
+ <TaggTypeahead component={component} {...props} />
+ ),
allowedSpacesCount: 0,
isInsertSpaceAfterMention: true,
textStyle: _textStyle(theme),