From 9322aede82815ba5a6bddf5b289692955d6e1d96 Mon Sep 17 00:00:00 2001
From: Ivan Chen <ivan@tagg.id>
Date: Fri, 30 Apr 2021 18:05:28 -0400
Subject: added display text parsing

---
 src/utils/comments.tsx | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 67 insertions(+)
 create mode 100644 src/utils/comments.tsx

(limited to 'src/utils/comments.tsx')

diff --git a/src/utils/comments.tsx b/src/utils/comments.tsx
new file mode 100644
index 00000000..a1f353d6
--- /dev/null
+++ b/src/utils/comments.tsx
@@ -0,0 +1,67 @@
+import React from 'react';
+import {Text} from 'react-native';
+import {
+  isMentionPartType,
+  parseValue,
+  Part,
+  PartType,
+} from 'react-native-controlled-mentions';
+import TaggTypeahead from '../components/common/TaggTypeahead';
+import {TAGG_LIGHT_BLUE} from '../constants';
+
+/**
+ * Part renderer
+ *
+ * https://github.com/dabakovich/react-native-controlled-mentions#rendering-mentioninputs-value
+ *
+ * @param part
+ * @param index
+ */
+const renderPart = (part: Part, index: number) => {
+  // Just plain text
+  if (!part.partType) {
+    return <Text key={index}>{part.text}</Text>;
+  }
+
+  // Mention type part
+  if (isMentionPartType(part.partType)) {
+    return (
+      <Text
+        key={`${index}-${part.data?.trigger}`}
+        style={part.partType.textStyle}
+        onPress={() => console.log('Pressed', part.data)}>
+        {part.text}
+      </Text>
+    );
+  }
+
+  // Other styled part types
+  return (
+    <Text key={`${index}-pattern`} style={part.partType.textStyle}>
+      {part.text}
+    </Text>
+  );
+};
+
+/**
+ * Value renderer. Parsing value to parts array and then mapping the array using 'renderPart'
+ *
+ * https://github.com/dabakovich/react-native-controlled-mentions#rendering-mentioninputs-value
+ *
+ * @param value - value from MentionInput
+ * @param partTypes - the part types array that you providing to MentionInput
+ */
+export const renderValue: React.FC = (value: string, partTypes: PartType[]) => {
+  const {parts} = parseValue(value, partTypes);
+  return <Text>{parts.map(renderPart)}</Text>;
+};
+
+export const mentionPartTypes: PartType[] = [
+  {
+    trigger: '@',
+    renderSuggestions: (props) => <TaggTypeahead {...props} />,
+    allowedSpacesCount: 0,
+    isInsertSpaceAfterMention: true,
+    textStyle: {color: TAGG_LIGHT_BLUE},
+  },
+];
-- 
cgit v1.2.3-70-g09d2


From c23feea922da063d88d031f25b72b53ba593ec04 Mon Sep 17 00:00:00 2001
From: Ivan Chen <ivan@tagg.id>
Date: Tue, 4 May 2021 20:07:03 -0400
Subject: fixed type warning

---
 src/components/comments/CommentTile.tsx |  7 +++++--
 src/utils/comments.tsx                  | 10 +++++++++-
 2 files changed, 14 insertions(+), 3 deletions(-)

(limited to 'src/utils/comments.tsx')

diff --git a/src/components/comments/CommentTile.tsx b/src/components/comments/CommentTile.tsx
index 37a249a8..12f32c95 100644
--- a/src/components/comments/CommentTile.tsx
+++ b/src/components/comments/CommentTile.tsx
@@ -14,7 +14,7 @@ import {deleteComment, getCommentsCount} from '../../services';
 import {RootState} from '../../store/rootReducer';
 import {CommentThreadType, CommentType, ScreenType} from '../../types';
 import {getTimePosted, normalize, SCREEN_WIDTH} from '../../utils';
-import {mentionPartTypes, renderValue} from '../../utils/comments';
+import {mentionPartTypes, renderTextWithMentions} from '../../utils/comments';
 import {ProfilePreview} from '../profile';
 import CommentsContainer from './CommentsContainer';
 
@@ -136,7 +136,10 @@ const CommentTile: React.FC<CommentTileProps> = ({
         />
         <TouchableOpacity style={styles.body} onPress={toggleAddComment}>
           <View style={styles.comment}>
-            {renderValue(commentObject.comment, mentionPartTypes)}
+            {renderTextWithMentions({
+              value: commentObject.comment,
+              partTypes: mentionPartTypes,
+            })}
           </View>
           <View style={styles.clockIconAndTime}>
             <ClockIcon style={styles.clockIcon} />
diff --git a/src/utils/comments.tsx b/src/utils/comments.tsx
index a1f353d6..c0b522f2 100644
--- a/src/utils/comments.tsx
+++ b/src/utils/comments.tsx
@@ -43,6 +43,11 @@ const renderPart = (part: Part, index: number) => {
   );
 };
 
+interface RenderProps {
+  value: string;
+  partTypes: PartType[];
+}
+
 /**
  * Value renderer. Parsing value to parts array and then mapping the array using 'renderPart'
  *
@@ -51,7 +56,10 @@ const renderPart = (part: Part, index: number) => {
  * @param value - value from MentionInput
  * @param partTypes - the part types array that you providing to MentionInput
  */
-export const renderValue: React.FC = (value: string, partTypes: PartType[]) => {
+export const renderTextWithMentions: React.FC<RenderProps> = ({
+  value,
+  partTypes,
+}) => {
   const {parts} = parseValue(value, partTypes);
   return <Text>{parts.map(renderPart)}</Text>;
 };
-- 
cgit v1.2.3-70-g09d2


From 7f9799c6693254f8eb6729c0977826694c28c437 Mon Sep 17 00:00:00 2001
From: Ivan Chen <ivan@tagg.id>
Date: Tue, 4 May 2021 20:46:27 -0400
Subject: added navigation to profile

---
 src/components/comments/CommentTile.tsx      | 34 ++++++++++++++------
 src/components/moments/MomentPostContent.tsx | 23 ++++++++++++--
 src/screens/profile/CaptionScreen.tsx        | 17 +++++-----
 src/utils/comments.tsx                       | 46 ++++++++++++++++++----------
 src/utils/users.ts                           | 24 +++++++++++++++
 5 files changed, 105 insertions(+), 39 deletions(-)

(limited to 'src/utils/comments.tsx')

diff --git a/src/components/comments/CommentTile.tsx b/src/components/comments/CommentTile.tsx
index 12f32c95..ce346af5 100644
--- a/src/components/comments/CommentTile.tsx
+++ b/src/components/comments/CommentTile.tsx
@@ -1,9 +1,10 @@
+import {useNavigation} from '@react-navigation/native';
 import React, {Fragment, useContext, useEffect, useRef, useState} from 'react';
 import {Alert, Animated, StyleSheet} from 'react-native';
 import {Text, View} from 'react-native-animatable';
 import {RectButton, TouchableOpacity} from 'react-native-gesture-handler';
 import Swipeable from 'react-native-gesture-handler/Swipeable';
-import {useSelector} from 'react-redux';
+import {useDispatch, useSelector, useStore} from 'react-redux';
 import Arrow from '../../assets/icons/back-arrow-colored.svg';
 import ClockIcon from '../../assets/icons/clock-icon-01.svg';
 import Trash from '../../assets/ionicons/trash-outline.svg';
@@ -12,9 +13,19 @@ import {ERROR_FAILED_TO_DELETE_COMMENT} from '../../constants/strings';
 import {CommentContext} from '../../screens/profile/MomentCommentsScreen';
 import {deleteComment, getCommentsCount} from '../../services';
 import {RootState} from '../../store/rootReducer';
-import {CommentThreadType, CommentType, ScreenType} from '../../types';
-import {getTimePosted, normalize, SCREEN_WIDTH} from '../../utils';
-import {mentionPartTypes, renderTextWithMentions} from '../../utils/comments';
+import {
+  CommentThreadType,
+  CommentType,
+  ScreenType,
+  UserType,
+} from '../../types';
+import {
+  getTimePosted,
+  navigateToProfile,
+  normalize,
+  SCREEN_WIDTH,
+} from '../../utils';
+import {renderTextWithMentions} from '../../utils/comments';
 import {ProfilePreview} from '../profile';
 import CommentsContainer from './CommentsContainer';
 
@@ -46,6 +57,9 @@ const CommentTile: React.FC<CommentTileProps> = ({
   const [shouldUpdateChild, setShouldUpdateChild] = useState(true);
   const swipeRef = useRef<Swipeable>(null);
   const {replyPosted} = useSelector((state: RootState) => state.user);
+  const state: RootState = useStore().getState();
+  const navigation = useNavigation();
+  const dispatch = useDispatch();
 
   useEffect(() => {
     if (shouldUpdateParent) {
@@ -135,12 +149,12 @@ const CommentTile: React.FC<CommentTileProps> = ({
           screenType={screenType}
         />
         <TouchableOpacity style={styles.body} onPress={toggleAddComment}>
-          <View style={styles.comment}>
-            {renderTextWithMentions({
-              value: commentObject.comment,
-              partTypes: mentionPartTypes,
-            })}
-          </View>
+          {renderTextWithMentions({
+            value: commentObject.comment,
+            styles: styles.comment,
+            onPress: (user: UserType) =>
+              navigateToProfile(state, dispatch, navigation, screenType, user),
+          })}
           <View style={styles.clockIconAndTime}>
             <ClockIcon style={styles.clockIcon} />
             <Text style={styles.date_time}>{' ' + timePosted}</Text>
diff --git a/src/components/moments/MomentPostContent.tsx b/src/components/moments/MomentPostContent.tsx
index d68ceaa3..03034925 100644
--- a/src/components/moments/MomentPostContent.tsx
+++ b/src/components/moments/MomentPostContent.tsx
@@ -1,8 +1,17 @@
+import {useNavigation} from '@react-navigation/native';
 import React, {useEffect} from 'react';
 import {Image, StyleSheet, Text, View, ViewProps} from 'react-native';
+import {useDispatch, useStore} from 'react-redux';
 import {getCommentsCount} from '../../services';
-import {ScreenType} from '../../types';
-import {getTimePosted, SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils';
+import {RootState} from '../../store/rootReducer';
+import {ScreenType, UserType} from '../../types';
+import {
+  getTimePosted,
+  navigateToProfile,
+  SCREEN_HEIGHT,
+  SCREEN_WIDTH,
+} from '../../utils';
+import {renderTextWithMentions} from '../../utils/comments';
 import {CommentsCount} from '../comments';
 
 interface MomentPostContentProps extends ViewProps {
@@ -22,6 +31,9 @@ const MomentPostContent: React.FC<MomentPostContentProps> = ({
 }) => {
   const [elapsedTime, setElapsedTime] = React.useState<string>();
   const [comments_count, setCommentsCount] = React.useState('');
+  const state: RootState = useStore().getState();
+  const navigation = useNavigation();
+  const dispatch = useDispatch();
 
   useEffect(() => {
     const fetchCommentsCount = async () => {
@@ -47,7 +59,12 @@ const MomentPostContent: React.FC<MomentPostContentProps> = ({
         />
         <Text style={styles.text}>{elapsedTime}</Text>
       </View>
-      <Text style={styles.captionText}>{caption}</Text>
+      {renderTextWithMentions({
+        value: caption,
+        styles: styles.captionText,
+        onPress: (user: UserType) =>
+          navigateToProfile(state, dispatch, navigation, screenType, user),
+      })}
     </View>
   );
 };
diff --git a/src/screens/profile/CaptionScreen.tsx b/src/screens/profile/CaptionScreen.tsx
index 156ee41c..041f0da2 100644
--- a/src/screens/profile/CaptionScreen.tsx
+++ b/src/screens/profile/CaptionScreen.tsx
@@ -11,9 +11,10 @@ import {
   TouchableWithoutFeedback,
   View,
 } from 'react-native';
+import {MentionInput} from 'react-native-controlled-mentions';
 import {Button} from 'react-native-elements';
 import {useDispatch, useSelector} from 'react-redux';
-import {SearchBackground, TaggBigInput} from '../../components';
+import {SearchBackground} from '../../components';
 import {CaptionScreenHeader} from '../../components/';
 import TaggLoadingIndicator from '../../components/common/TaggLoadingIndicator';
 import {TAGG_LIGHT_BLUE_2} from '../../constants';
@@ -26,6 +27,7 @@ import {
 } from '../../store/actions';
 import {RootState} from '../../store/rootReducer';
 import {SCREEN_WIDTH, StatusBarHeight} from '../../utils';
+import {mentionPartTypes} from '../../utils/comments';
 
 /**
  * Upload Screen to allow users to upload posts to Tagg
@@ -49,10 +51,6 @@ const CaptionScreen: React.FC<CaptionScreenProps> = ({route, navigation}) => {
   const [caption, setCaption] = useState('');
   const [loading, setLoading] = useState(false);
 
-  const handleCaptionUpdate = (newCaption: string) => {
-    setCaption(newCaption);
-  };
-
   const navigateToProfile = () => {
     //Since the logged In User is navigating to own profile, useXId is not required
     navigation.navigate('Profile', {
@@ -112,12 +110,13 @@ const CaptionScreen: React.FC<CaptionScreenProps> = ({route, navigation}) => {
               source={{uri: image.path}}
               resizeMode={'cover'}
             />
-            <TaggBigInput
-              style={styles.text}
-              multiline
+            <MentionInput
+              containerStyle={styles.text}
               placeholder="Write something....."
               placeholderTextColor="gray"
-              onChangeText={handleCaptionUpdate}
+              value={caption}
+              onChange={setCaption}
+              partTypes={mentionPartTypes}
             />
           </View>
         </KeyboardAvoidingView>
diff --git a/src/utils/comments.tsx b/src/utils/comments.tsx
index c0b522f2..47d26bb5 100644
--- a/src/utils/comments.tsx
+++ b/src/utils/comments.tsx
@@ -1,23 +1,26 @@
 import React from 'react';
-import {Text} from 'react-native';
+import {StyleProp, Text, TextStyle} from 'react-native';
 import {
   isMentionPartType,
   parseValue,
   Part,
   PartType,
 } from 'react-native-controlled-mentions';
+import {TouchableOpacity} from 'react-native-gesture-handler';
 import TaggTypeahead from '../components/common/TaggTypeahead';
 import {TAGG_LIGHT_BLUE} from '../constants';
+import {UserType} from '../types';
 
 /**
  * Part renderer
  *
  * https://github.com/dabakovich/react-native-controlled-mentions#rendering-mentioninputs-value
- *
- * @param part
- * @param index
  */
-const renderPart = (part: Part, index: number) => {
+const renderPart = (
+  part: Part,
+  index: number,
+  handlePress: (user: UserType) => void,
+) => {
   // Just plain text
   if (!part.partType) {
     return <Text key={index}>{part.text}</Text>;
@@ -26,12 +29,18 @@ const renderPart = (part: Part, index: number) => {
   // Mention type part
   if (isMentionPartType(part.partType)) {
     return (
-      <Text
+      <TouchableOpacity
         key={`${index}-${part.data?.trigger}`}
-        style={part.partType.textStyle}
-        onPress={() => console.log('Pressed', part.data)}>
-        {part.text}
-      </Text>
+        onPress={() => {
+          if (part.data) {
+            handlePress({
+              userId: part.data.id,
+              username: part.data.name,
+            });
+          }
+        }}>
+        <Text style={part.partType.textStyle}>{part.text}</Text>
+      </TouchableOpacity>
     );
   }
 
@@ -45,23 +54,26 @@ const renderPart = (part: Part, index: number) => {
 
 interface RenderProps {
   value: string;
-  partTypes: PartType[];
+  styles: StyleProp<TextStyle>;
+  onPress: (user: UserType) => void;
 }
 
 /**
  * Value renderer. Parsing value to parts array and then mapping the array using 'renderPart'
  *
  * https://github.com/dabakovich/react-native-controlled-mentions#rendering-mentioninputs-value
- *
- * @param value - value from MentionInput
- * @param partTypes - the part types array that you providing to MentionInput
  */
 export const renderTextWithMentions: React.FC<RenderProps> = ({
   value,
-  partTypes,
+  styles,
+  onPress,
 }) => {
-  const {parts} = parseValue(value, partTypes);
-  return <Text>{parts.map(renderPart)}</Text>;
+  const {parts} = parseValue(value, mentionPartTypes);
+  return (
+    <Text style={styles}>
+      {parts.map((part, index) => renderPart(part, index, onPress))}
+    </Text>
+  );
 };
 
 export const mentionPartTypes: PartType[] = [
diff --git a/src/utils/users.ts b/src/utils/users.ts
index abadaf6e..c167ac2f 100644
--- a/src/utils/users.ts
+++ b/src/utils/users.ts
@@ -1,4 +1,6 @@
 import AsyncStorage from '@react-native-community/async-storage';
+import {NavigationProp} from '@react-navigation/core';
+import {Dispatch} from 'react';
 import {INTEGRATED_SOCIAL_LIST} from '../constants';
 import {isUserBlocked, loadSocialPosts} from '../services';
 import {
@@ -199,3 +201,25 @@ export const canViewProfile = (
   }
   return false;
 };
+
+export const navigateToProfile = async (
+  state: RootState,
+  dispatch: any,
+  navigation: any,
+  screenType: ScreenType,
+  user: UserType,
+) => {
+  const loggedInUserId = state.user.user.userId;
+  const {userId, username} = user;
+  if (!userXInStore(state, screenType, userId)) {
+    await fetchUserX(
+      dispatch,
+      {userId: userId, username: username},
+      screenType,
+    );
+  }
+  navigation.push('Profile', {
+    userXId: userId === loggedInUserId ? undefined : userId,
+    screenType,
+  });
+};
-- 
cgit v1.2.3-70-g09d2


From 05bcb134a026ee98919438044a63a656f60e74f2 Mon Sep 17 00:00:00 2001
From: Ivan Chen <ivan@tagg.id>
Date: Tue, 4 May 2021 21:06:48 -0400
Subject: fixed layout issue

---
 src/utils/comments.tsx | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

(limited to 'src/utils/comments.tsx')

diff --git a/src/utils/comments.tsx b/src/utils/comments.tsx
index 47d26bb5..a71e3857 100644
--- a/src/utils/comments.tsx
+++ b/src/utils/comments.tsx
@@ -6,7 +6,6 @@ import {
   Part,
   PartType,
 } from 'react-native-controlled-mentions';
-import {TouchableOpacity} from 'react-native-gesture-handler';
 import TaggTypeahead from '../components/common/TaggTypeahead';
 import {TAGG_LIGHT_BLUE} from '../constants';
 import {UserType} from '../types';
@@ -29,8 +28,9 @@ const renderPart = (
   // Mention type part
   if (isMentionPartType(part.partType)) {
     return (
-      <TouchableOpacity
+      <Text
         key={`${index}-${part.data?.trigger}`}
+        style={part.partType.textStyle}
         onPress={() => {
           if (part.data) {
             handlePress({
@@ -39,8 +39,8 @@ const renderPart = (
             });
           }
         }}>
-        <Text style={part.partType.textStyle}>{part.text}</Text>
-      </TouchableOpacity>
+        {part.text}
+      </Text>
     );
   }
 
-- 
cgit v1.2.3-70-g09d2

