From 755f4f540d3e759ff9ad3bc35c64b6f7fc83998b Mon Sep 17 00:00:00 2001
From: Ashm Walia <ashmwalia@outlook.com>
Date: Mon, 25 Jan 2021 18:00:44 -0800
Subject: Add provision to show and hide replies

---
 src/components/comments/CommentTile.tsx | 122 ++++++++++++++++++++++++++------
 1 file changed, 102 insertions(+), 20 deletions(-)

(limited to 'src/components/comments/CommentTile.tsx')

diff --git a/src/components/comments/CommentTile.tsx b/src/components/comments/CommentTile.tsx
index 47f25a53..4221fd54 100644
--- a/src/components/comments/CommentTile.tsx
+++ b/src/components/comments/CommentTile.tsx
@@ -1,10 +1,19 @@
-import React from 'react';
+import React, {useState} from 'react';
 import {Text, View} from 'react-native-animatable';
 import {ProfilePreview} from '../profile';
-import {CommentType, ScreenType} from '../../types';
+import {CommentType, ScreenType, TypeOfComment} from '../../types';
 import {StyleSheet} from 'react-native';
-import {getTimePosted} from '../../utils';
+import {
+  getTimePosted,
+  normalize,
+  SCREEN_HEIGHT,
+  SCREEN_WIDTH,
+} from '../../utils';
 import ClockIcon from '../../assets/icons/clock-icon-01.svg';
+import {COMMENT_REPLIES} from '../../constants';
+import BackIcon from '../../assets/icons/back-arrow-colored.svg';
+import {TouchableOpacity} from 'react-native-gesture-handler';
+// import CommentsContainer from './CommentsContainer';
 
 /**
  * Displays users's profile picture, comment posted by them and the time difference between now and when a comment was posted.
@@ -13,33 +22,78 @@ import ClockIcon from '../../assets/icons/clock-icon-01.svg';
 interface CommentTileProps {
   comment_object: CommentType;
   screenType: ScreenType;
+  typeOfComment: TypeOfComment;
 }
 
 const CommentTile: React.FC<CommentTileProps> = ({
   comment_object,
   screenType,
+  typeOfComment,
 }) => {
   const timePosted = getTimePosted(comment_object.date_created);
+  const [showReplies, setShowReplies] = useState<boolean>(false);
+
+  const isThread = typeOfComment === 'Thread';
+
   return (
-    <View style={styles.container}>
-      <ProfilePreview
-        profilePreview={{
-          id: comment_object.commenter.id,
-          username: comment_object.commenter.username,
-          first_name: comment_object.commenter.first_name,
-          last_name: comment_object.commenter.last_name,
-        }}
-        previewType={'Comment'}
-        screenType={screenType}
-      />
-      <View style={styles.body}>
-        <Text style={styles.comment}>{comment_object.comment}</Text>
-        <View style={styles.clockIconAndTime}>
-          <ClockIcon style={styles.clockIcon} />
-          <Text style={styles.date_time}>{' ' + timePosted}</Text>
+    <>
+      <View style={styles.container}>
+        <ProfilePreview
+          profilePreview={{
+            id: comment_object.commenter.id,
+            username: comment_object.commenter.username,
+            first_name: comment_object.commenter.first_name,
+            last_name: comment_object.commenter.last_name,
+          }}
+          previewType={'Comment'}
+          screenType={screenType}
+        />
+        <View style={styles.body}>
+          <Text style={styles.comment}>{comment_object.comment}</Text>
+          <View style={styles.clockIconAndTime}>
+            <ClockIcon style={styles.clockIcon} />
+            <Text style={styles.date_time}>{' ' + timePosted}</Text>
+            {typeOfComment === 'Comment' && (
+              <>
+                <TouchableOpacity
+                  onPress={() => {
+                    setShowReplies(!showReplies);
+                  }}>
+                  <View style={styles.repliesTextAndIconContainer}>
+                    <Text style={styles.repliesText}>
+                      {showReplies ? 'Hide' : 'Replies'}
+                    </Text>
+                    <BackIcon
+                      width={12}
+                      height={11}
+                      color={COMMENT_REPLIES}
+                      style={
+                        !showReplies
+                          ? styles.repliesDownArrow
+                          : styles.repliesUpArrow
+                      }
+                    />
+                  </View>
+                </TouchableOpacity>
+              </>
+            )}
+          </View>
         </View>
       </View>
-    </View>
+      {/* {showReplies && (
+        <View style={styles.repliesBody}>
+          <CommentsContainer
+            moment_id={'5a9d6023-bc62-4588-a3dc-8de2c9c370e0'}
+            screenType={screenType}
+            setNewCommentsAvailable={(value: boolean) => {
+              console.log(value);
+            }}
+            newCommentsAvailable={true}
+            typeOfComment={'Thread'}
+          />
+        </View>
+      )} */}
+    </>
   );
 };
 
@@ -61,6 +115,7 @@ const styles = StyleSheet.create({
   },
   date_time: {
     color: 'gray',
+    fontSize: normalize(12),
   },
   clockIcon: {
     width: 12,
@@ -71,6 +126,33 @@ const styles = StyleSheet.create({
     flexDirection: 'row',
     marginBottom: '3%',
   },
+
+  repliesTextAndIconContainer: {
+    marginLeft: SCREEN_WIDTH * 0.37,
+    flexDirection: 'row',
+  },
+
+  repliesText: {
+    color: COMMENT_REPLIES,
+    fontWeight: '500',
+    fontSize: normalize(12),
+    marginRight: '3%',
+  },
+
+  repliesBody: {
+    width: SCREEN_WIDTH,
+    height: SCREEN_HEIGHT * 0.8,
+  },
+
+  repliesDownArrow: {
+    transform: [{rotate: '270deg'}],
+    marginTop: '7%',
+  },
+
+  repliesUpArrow: {
+    transform: [{rotate: '90deg'}],
+    marginTop: '7%',
+  },
 });
 
 export default CommentTile;
-- 
cgit v1.2.3-70-g09d2


From 85c0f668665696ba8127ee1ea436d10ec0af955f Mon Sep 17 00:00:00 2001
From: Ashm Walia <ashmwalia@outlook.com>
Date: Wed, 27 Jan 2021 08:24:43 -0800
Subject: Pre-final

---
 src/components/comments/AddComment.tsx       |  34 +++++---
 src/components/comments/CommentTile.tsx      | 113 +++++++++++++++------------
 src/components/moments/MomentPostContent.tsx |   8 +-
 src/constants/api.ts                         |   1 +
 src/routes/Routes.tsx                        |   2 +-
 src/screens/profile/MomentCommentsScreen.tsx |  23 +++++-
 src/services/MomentServices.ts               |   8 ++
 src/services/index.ts                        |   1 +
 src/types/types.ts                           |   1 +
 9 files changed, 122 insertions(+), 69 deletions(-)

(limited to 'src/components/comments/CommentTile.tsx')

diff --git a/src/components/comments/AddComment.tsx b/src/components/comments/AddComment.tsx
index 7b04085d..86f4170c 100644
--- a/src/components/comments/AddComment.tsx
+++ b/src/components/comments/AddComment.tsx
@@ -1,4 +1,4 @@
-import React, {useEffect} from 'react';
+import React, {useEffect, useRef} from 'react';
 import {
   Image,
   Keyboard,
@@ -11,7 +11,7 @@ import {TextInput, TouchableOpacity} from 'react-native-gesture-handler';
 import {useSelector} from 'react-redux';
 import UpArrowIcon from '../../assets/icons/up_arrow.svg';
 import {TAGG_LIGHT_BLUE} from '../../constants';
-import {postMomentComment} from '../../services';
+import {postComment} from '../../services';
 import {RootState} from '../../store/rootreducer';
 import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils';
 
@@ -23,28 +23,27 @@ import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils';
 
 export interface AddCommentProps {
   setNewCommentsAvailable: Function;
-  moment_id: string;
+  objectId: string;
   placeholderText: string;
+  isThreadInFocus: boolean;
 }
 
 const AddComment: React.FC<AddCommentProps> = ({
   setNewCommentsAvailable,
-  moment_id,
+  objectId,
   placeholderText,
+  isThreadInFocus,
 }) => {
   const [comment, setComment] = React.useState('');
   const [keyboardVisible, setKeyboardVisible] = React.useState(false);
 
-  const {
-    avatar,
-    user: {userId},
-  } = useSelector((state: RootState) => state.user);
+  const {avatar} = useSelector((state: RootState) => state.user);
 
-  const postComment = async () => {
-    const postedComment = await postMomentComment(
-      userId,
+  const addComment = async () => {
+    const postedComment = await postComment(
       comment.trim(),
-      moment_id,
+      objectId,
+      isThreadInFocus,
     );
 
     if (postedComment) {
@@ -65,6 +64,13 @@ const AddComment: React.FC<AddCommentProps> = ({
     return () => Keyboard.removeListener('keyboardWillHide', hideKeyboard);
   }, []);
 
+  const ref = useRef<TextInput>(null);
+  useEffect(() => {
+    if (isThreadInFocus) {
+      ref.current?.focus();
+    }
+  }, [isThreadInFocus]);
+
   return (
     <KeyboardAvoidingView
       behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
@@ -91,9 +97,10 @@ const AddComment: React.FC<AddCommentProps> = ({
             value={comment}
             autoCorrect={false}
             multiline={true}
+            ref={ref}
           />
           <View style={styles.submitButton}>
-            <TouchableOpacity style={styles.submitButton} onPress={postComment}>
+            <TouchableOpacity style={styles.submitButton} onPress={addComment}>
               <UpArrowIcon width={35} height={35} color={'white'} />
             </TouchableOpacity>
           </View>
@@ -102,6 +109,7 @@ const AddComment: React.FC<AddCommentProps> = ({
     </KeyboardAvoidingView>
   );
 };
+
 const styles = StyleSheet.create({
   container: {
     backgroundColor: '#f7f7f7',
diff --git a/src/components/comments/CommentTile.tsx b/src/components/comments/CommentTile.tsx
index 4221fd54..f11c5e33 100644
--- a/src/components/comments/CommentTile.tsx
+++ b/src/components/comments/CommentTile.tsx
@@ -3,17 +3,12 @@ import {Text, View} from 'react-native-animatable';
 import {ProfilePreview} from '../profile';
 import {CommentType, ScreenType, TypeOfComment} from '../../types';
 import {StyleSheet} from 'react-native';
-import {
-  getTimePosted,
-  normalize,
-  SCREEN_HEIGHT,
-  SCREEN_WIDTH,
-} from '../../utils';
 import ClockIcon from '../../assets/icons/clock-icon-01.svg';
 import {COMMENT_REPLIES} from '../../constants';
-import BackIcon from '../../assets/icons/back-arrow-colored.svg';
 import {TouchableOpacity} from 'react-native-gesture-handler';
-// import CommentsContainer from './CommentsContainer';
+import {getTimePosted, normalize, SCREEN_WIDTH} from '../../utils';
+import Arrow from '../../assets/icons/back-arrow-colored.svg';
+import CommentsContainer from './CommentsContainer';
 
 /**
  * Displays users's profile picture, comment posted by them and the time difference between now and when a comment was posted.
@@ -23,21 +18,43 @@ interface CommentTileProps {
   comment_object: CommentType;
   screenType: ScreenType;
   typeOfComment: TypeOfComment;
+  setCommentObjectInFocus?: (comment: CommentType | undefined) => void;
 }
 
 const CommentTile: React.FC<CommentTileProps> = ({
   comment_object,
   screenType,
   typeOfComment,
+  setCommentObjectInFocus,
 }) => {
   const timePosted = getTimePosted(comment_object.date_created);
   const [showReplies, setShowReplies] = useState<boolean>(false);
 
-  const isThread = typeOfComment === 'Thread';
+  const toggleReplies = () => {
+    if (setCommentObjectInFocus) {
+      if (!showReplies) {
+        setCommentObjectInFocus(comment_object);
+      } else {
+        setCommentObjectInFocus(undefined);
+      }
+    }
+    setShowReplies(!showReplies);
+  };
+
+  const getRepliesText = () =>
+    showReplies
+      ? 'Hide'
+      : comment_object.replies_count > 0
+      ? `Replies (${comment_object.replies_count})`
+      : 'Replies';
 
   return (
     <>
-      <View style={styles.container}>
+      <View
+        style={[
+          styles.container,
+          typeOfComment === 'Thread' ? styles.moreMarginWithThread : {},
+        ]}>
         <ProfilePreview
           profilePreview={{
             id: comment_object.commenter.id,
@@ -48,70 +65,66 @@ const CommentTile: React.FC<CommentTileProps> = ({
           previewType={'Comment'}
           screenType={screenType}
         />
-        <View style={styles.body}>
+        <TouchableOpacity style={styles.body} onPress={toggleReplies}>
           <Text style={styles.comment}>{comment_object.comment}</Text>
           <View style={styles.clockIconAndTime}>
             <ClockIcon style={styles.clockIcon} />
             <Text style={styles.date_time}>{' ' + timePosted}</Text>
-            {typeOfComment === 'Comment' && (
-              <>
-                <TouchableOpacity
-                  onPress={() => {
-                    setShowReplies(!showReplies);
-                  }}>
-                  <View style={styles.repliesTextAndIconContainer}>
-                    <Text style={styles.repliesText}>
-                      {showReplies ? 'Hide' : 'Replies'}
-                    </Text>
-                    <BackIcon
-                      width={12}
-                      height={11}
-                      color={COMMENT_REPLIES}
-                      style={
-                        !showReplies
-                          ? styles.repliesDownArrow
-                          : styles.repliesUpArrow
-                      }
-                    />
-                  </View>
-                </TouchableOpacity>
-              </>
+            <View style={styles.flexer} />
+            {typeOfComment === 'Comment' && comment_object.replies_count > 0 && (
+              <View style={styles.repliesTextAndIconContainer}>
+                <Text style={styles.repliesText}>{getRepliesText()}</Text>
+                <Arrow
+                  width={12}
+                  height={11}
+                  color={COMMENT_REPLIES}
+                  style={
+                    !showReplies
+                      ? styles.repliesDownArrow
+                      : styles.repliesUpArrow
+                  }
+                />
+              </View>
             )}
           </View>
-        </View>
+        </TouchableOpacity>
       </View>
-      {/* {showReplies && (
-        <View style={styles.repliesBody}>
+      {showReplies && (
+        <View
+          style={{
+            width: SCREEN_WIDTH,
+          }}>
           <CommentsContainer
-            moment_id={'5a9d6023-bc62-4588-a3dc-8de2c9c370e0'}
+            objectId={comment_object.comment_id}
             screenType={screenType}
-            setNewCommentsAvailable={(value: boolean) => {
-              console.log(value);
-            }}
+            setNewCommentsAvailable={() => {}}
             newCommentsAvailable={true}
             typeOfComment={'Thread'}
           />
         </View>
-      )} */}
+      )}
     </>
   );
 };
 
 const styles = StyleSheet.create({
   container: {
-    marginLeft: '3%',
-    marginRight: '3%',
+    marginHorizontal: '3%',
     borderBottomWidth: 1,
     borderColor: 'lightgray',
     marginBottom: '3%',
+    flexDirection: 'column',
+    flex: 1,
+  },
+  moreMarginWithThread: {
+    marginHorizontal: '7%',
   },
   body: {
     marginLeft: 56,
   },
   comment: {
-    position: 'relative',
-    top: -5,
     marginBottom: '2%',
+    top: -5,
   },
   date_time: {
     color: 'gray',
@@ -127,9 +140,13 @@ const styles = StyleSheet.create({
     marginBottom: '3%',
   },
 
+  flexer: {
+    flex: 1,
+  },
+
   repliesTextAndIconContainer: {
-    marginLeft: SCREEN_WIDTH * 0.37,
     flexDirection: 'row',
+    alignItems: 'center',
   },
 
   repliesText: {
@@ -138,10 +155,8 @@ const styles = StyleSheet.create({
     fontSize: normalize(12),
     marginRight: '3%',
   },
-
   repliesBody: {
     width: SCREEN_WIDTH,
-    height: SCREEN_HEIGHT * 0.8,
   },
 
   repliesDownArrow: {
diff --git a/src/components/moments/MomentPostContent.tsx b/src/components/moments/MomentPostContent.tsx
index 508b6d9f..d68ceaa3 100644
--- a/src/components/moments/MomentPostContent.tsx
+++ b/src/components/moments/MomentPostContent.tsx
@@ -1,6 +1,6 @@
 import React, {useEffect} from 'react';
 import {Image, StyleSheet, Text, View, ViewProps} from 'react-native';
-import {getMomentCommentsCount} from '../../services';
+import {getCommentsCount} from '../../services';
 import {ScreenType} from '../../types';
 import {getTimePosted, SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils';
 import {CommentsCount} from '../comments';
@@ -24,8 +24,12 @@ const MomentPostContent: React.FC<MomentPostContentProps> = ({
   const [comments_count, setCommentsCount] = React.useState('');
 
   useEffect(() => {
+    const fetchCommentsCount = async () => {
+      const count = await getCommentsCount(momentId, false);
+      setCommentsCount(count);
+    };
     setElapsedTime(getTimePosted(dateTime));
-    getMomentCommentsCount(momentId, setCommentsCount);
+    fetchCommentsCount();
   }, [dateTime, momentId]);
 
   return (
diff --git a/src/constants/api.ts b/src/constants/api.ts
index 701070eb..32631be0 100644
--- a/src/constants/api.ts
+++ b/src/constants/api.ts
@@ -30,6 +30,7 @@ export const MOMENT_CATEGORY_ENDPOINT: string = API_URL + 'moment-category/';
 export const NOTIFICATIONS_ENDPOINT: string = API_URL + 'notifications/';
 export const DISCOVER_ENDPOINT: string = API_URL + 'discover/';
 export const WAITLIST_USER_ENDPOINT: string = API_URL + 'waitlist-user/';
+export const COMMENT_THREAD_ENDPOINT: string = API_URL + 'reply/';
 
 // Register as FCM device
 export const FCM_ENDPOINT: string = API_URL + 'fcm/';
diff --git a/src/routes/Routes.tsx b/src/routes/Routes.tsx
index a14f1576..536c7d04 100644
--- a/src/routes/Routes.tsx
+++ b/src/routes/Routes.tsx
@@ -33,7 +33,7 @@ const Routes: React.FC = () => {
     });
 
     if (!userId) {
-      userLogin(dispatch, {userId: '', username: ''});
+      // userLogin(dispatch, {userId: '', username: ''});
     } else {
       SplashScreen.hide();
     }
diff --git a/src/screens/profile/MomentCommentsScreen.tsx b/src/screens/profile/MomentCommentsScreen.tsx
index 9fd5aaa0..764b9228 100644
--- a/src/screens/profile/MomentCommentsScreen.tsx
+++ b/src/screens/profile/MomentCommentsScreen.tsx
@@ -6,7 +6,9 @@ import BackIcon from '../../assets/icons/back-arrow.svg';
 import {TabsGradient} from '../../components';
 import {AddComment} from '../../components/';
 import CommentsContainer from '../../components/comments/CommentsContainer';
+import {ADD_COMMENT_TEXT} from '../../constants/strings';
 import {MainStackParams} from '../../routes/main';
+import {CommentType} from '../../types';
 import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils';
 
 /**
@@ -27,8 +29,12 @@ interface MomentCommentsScreenProps {
 const MomentCommentsScreen: React.FC<MomentCommentsScreenProps> = ({route}) => {
   const navigation = useNavigation();
   const {moment_id, screenType} = route.params;
-  const [newCommentsAvailable, setNewCommentsAvailable] = useState(true);
+
   const [commentsLength, setCommentsLength] = useState<number>(0);
+  const [newCommentsAvailable, setNewCommentsAvailable] = React.useState(true);
+  const [commentObjectInFocus, setCommentObjectInFocus] = useState<
+    CommentType | undefined
+  >(undefined);
 
   return (
     <View style={styles.background}>
@@ -45,17 +51,26 @@ const MomentCommentsScreen: React.FC<MomentCommentsScreenProps> = ({route}) => {
         </View>
         <View style={styles.body}>
           <CommentsContainer
-            moment_id={moment_id}
+            objectId={moment_id}
             screenType={screenType}
             setCommentsLength={setCommentsLength}
             newCommentsAvailable={newCommentsAvailable}
             setNewCommentsAvailable={setNewCommentsAvailable}
+            setCommentObjectInFocus={setCommentObjectInFocus}
+            commentObjectInFocus={commentObjectInFocus}
             typeOfComment={'Comment'}
           />
           <AddComment
-            placeholderText={'Add a comment..'}
+            placeholderText={
+              commentObjectInFocus
+                ? ADD_COMMENT_TEXT(commentObjectInFocus.commenter.username)
+                : ADD_COMMENT_TEXT()
+            }
             setNewCommentsAvailable={setNewCommentsAvailable}
-            moment_id={moment_id}
+            objectId={
+              commentObjectInFocus ? commentObjectInFocus.comment_id : moment_id
+            }
+            isThreadInFocus={commentObjectInFocus ? true : false}
           />
         </View>
       </SafeAreaView>
diff --git a/src/services/MomentServices.ts b/src/services/MomentServices.ts
index 77740e7e..8399eea3 100644
--- a/src/services/MomentServices.ts
+++ b/src/services/MomentServices.ts
@@ -1,5 +1,6 @@
 import {CommentType} from './../types/types';
 import AsyncStorage from '@react-native-community/async-storage';
+<<<<<<< Updated upstream
 import {Alert} from 'react-native';
 import RNFetchBlob from 'rn-fetch-blob';
 import {
@@ -96,6 +97,13 @@ export const getMomentCommentsCount = async (
   }
 };
 
+=======
+import RNFetchBlob from 'rn-fetch-blob';
+import {MOMENTS_ENDPOINT, MOMENT_THUMBNAIL_ENDPOINT} from '../constants';
+import {MomentType} from '../types';
+import {checkImageUploadStatus} from '../utils';
+
+>>>>>>> Stashed changes
 export const postMoment: (
   fileName: string,
   uri: string,
diff --git a/src/services/index.ts b/src/services/index.ts
index 56cefddd..f558247f 100644
--- a/src/services/index.ts
+++ b/src/services/index.ts
@@ -9,3 +9,4 @@ export * from './MomentCategoryService';
 export * from './NotificationService';
 export * from './FCMService';
 export * from './WaitlistUserService';
+export * from './CommentService';
diff --git a/src/types/types.ts b/src/types/types.ts
index b29ecbd9..0c0f9d8b 100644
--- a/src/types/types.ts
+++ b/src/types/types.ts
@@ -91,6 +91,7 @@ export interface CommentType {
   comment: string;
   date_created: string;
   moment_id: string;
+  replies_count: number;
   commenter: ProfilePreviewType;
 }
 
-- 
cgit v1.2.3-70-g09d2


From 2f5f9df6dec1e905f3abf37d124ecd92d0e3a3d9 Mon Sep 17 00:00:00 2001
From: Ashm Walia <ashmwalia@outlook.com>
Date: Wed, 27 Jan 2021 08:29:56 -0800
Subject: Pre-final

---
 src/components/comments/AddComment.tsx        |  17 +++--
 src/components/comments/CommentTile.tsx       |  14 ++++
 src/components/comments/CommentsContainer.tsx |  37 +++++++---
 src/constants/strings.ts                      |   2 +
 src/routes/Routes.tsx                         |   2 +-
 src/screens/profile/MomentCommentsScreen.tsx  |   5 +-
 src/services/CommentService.ts                | 101 ++++++++++++++++++++++++++
 src/services/MomentServices.ts                | 100 -------------------------
 8 files changed, 158 insertions(+), 120 deletions(-)
 create mode 100644 src/services/CommentService.ts

(limited to 'src/components/comments/CommentTile.tsx')

diff --git a/src/components/comments/AddComment.tsx b/src/components/comments/AddComment.tsx
index 86f4170c..46086e81 100644
--- a/src/components/comments/AddComment.tsx
+++ b/src/components/comments/AddComment.tsx
@@ -25,14 +25,14 @@ export interface AddCommentProps {
   setNewCommentsAvailable: Function;
   objectId: string;
   placeholderText: string;
-  isThreadInFocus: boolean;
+  isCommentInFocus: boolean;
 }
 
 const AddComment: React.FC<AddCommentProps> = ({
   setNewCommentsAvailable,
   objectId,
   placeholderText,
-  isThreadInFocus,
+  isCommentInFocus,
 }) => {
   const [comment, setComment] = React.useState('');
   const [keyboardVisible, setKeyboardVisible] = React.useState(false);
@@ -43,7 +43,7 @@ const AddComment: React.FC<AddCommentProps> = ({
     const postedComment = await postComment(
       comment.trim(),
       objectId,
-      isThreadInFocus,
+      isCommentInFocus,
     );
 
     if (postedComment) {
@@ -65,11 +65,13 @@ const AddComment: React.FC<AddCommentProps> = ({
   }, []);
 
   const ref = useRef<TextInput>(null);
+
+  //If a comment is in Focus, bring the keyboard up so user is able to type in a reply
   useEffect(() => {
-    if (isThreadInFocus) {
+    if (isCommentInFocus) {
       ref.current?.focus();
     }
-  }, [isThreadInFocus]);
+  }, [isCommentInFocus]);
 
   return (
     <KeyboardAvoidingView
@@ -78,7 +80,7 @@ const AddComment: React.FC<AddCommentProps> = ({
       <View
         style={[
           styles.container,
-          keyboardVisible ? {backgroundColor: '#fff'} : {},
+          keyboardVisible ? styles.whiteBackround : {},
         ]}>
         <View style={styles.textContainer}>
           <Image
@@ -150,6 +152,9 @@ const styles = StyleSheet.create({
     marginVertical: '2%',
     alignSelf: 'flex-end',
   },
+  whiteBackround: {
+    backgroundColor: '#fff',
+  },
 });
 
 export default AddComment;
diff --git a/src/components/comments/CommentTile.tsx b/src/components/comments/CommentTile.tsx
index f11c5e33..9a1607f7 100644
--- a/src/components/comments/CommentTile.tsx
+++ b/src/components/comments/CommentTile.tsx
@@ -30,6 +30,13 @@ const CommentTile: React.FC<CommentTileProps> = ({
   const timePosted = getTimePosted(comment_object.date_created);
   const [showReplies, setShowReplies] = useState<boolean>(false);
 
+  /**
+   * Case : A COMMENT IS IN FOCUS && REPLY SECTION IS HIDDEN
+   *     Bring the current comment to focus
+   * Case : No COMMENT IS IN FOCUS && REPLY SECTION IS SHOWN
+   *     Unfocus comment in focus
+   * In any case toggle value of showReplies
+   */
   const toggleReplies = () => {
     if (setCommentObjectInFocus) {
       if (!showReplies) {
@@ -41,6 +48,9 @@ const CommentTile: React.FC<CommentTileProps> = ({
     setShowReplies(!showReplies);
   };
 
+  /**
+   * Method to compute text to be shown for replies button
+   */
   const getRepliesText = () =>
     showReplies
       ? 'Hide'
@@ -71,6 +81,8 @@ const CommentTile: React.FC<CommentTileProps> = ({
             <ClockIcon style={styles.clockIcon} />
             <Text style={styles.date_time}>{' ' + timePosted}</Text>
             <View style={styles.flexer} />
+
+            {/*** Show replies text only if there are some replies present */}
             {typeOfComment === 'Comment' && comment_object.replies_count > 0 && (
               <View style={styles.repliesTextAndIconContainer}>
                 <Text style={styles.repliesText}>{getRepliesText()}</Text>
@@ -89,6 +101,8 @@ const CommentTile: React.FC<CommentTileProps> = ({
           </View>
         </TouchableOpacity>
       </View>
+
+      {/*** Show replies if toggle state is true */}
       {showReplies && (
         <View
           style={{
diff --git a/src/components/comments/CommentsContainer.tsx b/src/components/comments/CommentsContainer.tsx
index 81ae8e1e..5aa32511 100644
--- a/src/components/comments/CommentsContainer.tsx
+++ b/src/components/comments/CommentsContainer.tsx
@@ -3,54 +3,66 @@ import {StyleSheet} from 'react-native';
 import {ScrollView} from 'react-native-gesture-handler';
 import {useDispatch} from 'react-redux';
 import {CommentTile} from '.';
-import {getMomentComments} from '../../services';
+import {getComments} from '../../services';
 import {CommentType, ScreenType, TypeOfComment} from '../../types';
 export type CommentsContainerProps = {
   screenType: ScreenType;
-  moment_id: string;
+
+  //objectId can be either moment_id or comment_id
+  objectId: string;
   setCommentsLength?: (count: number) => void;
   newCommentsAvailable: boolean;
   setNewCommentsAvailable: (value: boolean) => void;
   typeOfComment: TypeOfComment;
+  setCommentObjectInFocus?: (comment: CommentType | undefined) => void;
+  commentObjectInFocus?: CommentType;
 };
 
+/**
+ * Comments Container to be used for both comments and replies
+ */
+
 const CommentsContainer: React.FC<CommentsContainerProps> = ({
   screenType,
-  moment_id,
+  objectId,
   setCommentsLength,
   newCommentsAvailable,
   setNewCommentsAvailable,
   typeOfComment,
+  setCommentObjectInFocus,
+  commentObjectInFocus,
 }) => {
   const [commentsList, setCommentsList] = useState<CommentType[]>([]);
   const dispatch = useDispatch();
   const ref = useRef<ScrollView>(null);
 
   useEffect(() => {
+    //Scroll only if a new comment and not a reply was posted
+    const shouldScroll = () =>
+      typeOfComment === 'Comment' && !commentObjectInFocus;
     const loadComments = async () => {
-      console.log(moment_id);
-      const comments = await getMomentComments(moment_id);
+      const comments = await getComments(objectId, typeOfComment === 'Thread');
       setCommentsList(comments);
       if (setCommentsLength) {
         setCommentsLength(comments.length);
       }
-      console.log(comments);
       setNewCommentsAvailable(false);
     };
     if (newCommentsAvailable) {
       loadComments();
-      setTimeout(() => {
-        ref.current?.scrollToEnd({
-          animated: true,
-        });
-      }, 500);
+      if (shouldScroll()) {
+        setTimeout(() => {
+          ref.current?.scrollToEnd();
+        }, 500);
+      }
     }
   }, [
     dispatch,
-    moment_id,
+    objectId,
     newCommentsAvailable,
     setNewCommentsAvailable,
     setCommentsLength,
+    typeOfComment,
   ]);
 
   return (
@@ -65,6 +77,7 @@ const CommentsContainer: React.FC<CommentsContainerProps> = ({
             comment_object={comment}
             screenType={screenType}
             typeOfComment={typeOfComment}
+            setCommentObjectInFocus={setCommentObjectInFocus}
           />
         ))}
     </ScrollView>
diff --git a/src/constants/strings.ts b/src/constants/strings.ts
index a1793658..77ded7be 100644
--- a/src/constants/strings.ts
+++ b/src/constants/strings.ts
@@ -1,7 +1,9 @@
+
 /* eslint-disable */
 // Below is the regex to convert this into a csv for the Google Sheet
 // export const (.*) = .*?(['|"|`])(.*)\2;
 // replace with: $1\t$3
+export const ADD_COMMENT_TEXT = (username?: string) => username ? `Reply to ${username}` : 'Add a comment...'
 export const COMING_SOON_MSG = 'Creating more fun things for you, surprises coming soon 😉';
 export const ERROR_AUTHENTICATION = 'An error occurred during authentication. Please login again!';
 export const ERROR_CATEGORY_CREATION = 'There was a problem creating your categories. Please refresh and try again.';
diff --git a/src/routes/Routes.tsx b/src/routes/Routes.tsx
index 536c7d04..a14f1576 100644
--- a/src/routes/Routes.tsx
+++ b/src/routes/Routes.tsx
@@ -33,7 +33,7 @@ const Routes: React.FC = () => {
     });
 
     if (!userId) {
-      // userLogin(dispatch, {userId: '', username: ''});
+      userLogin(dispatch, {userId: '', username: ''});
     } else {
       SplashScreen.hide();
     }
diff --git a/src/screens/profile/MomentCommentsScreen.tsx b/src/screens/profile/MomentCommentsScreen.tsx
index 764b9228..58422f0f 100644
--- a/src/screens/profile/MomentCommentsScreen.tsx
+++ b/src/screens/profile/MomentCommentsScreen.tsx
@@ -30,8 +30,11 @@ const MomentCommentsScreen: React.FC<MomentCommentsScreenProps> = ({route}) => {
   const navigation = useNavigation();
   const {moment_id, screenType} = route.params;
 
+  //Receives comment length from child CommentsContainer
   const [commentsLength, setCommentsLength] = useState<number>(0);
   const [newCommentsAvailable, setNewCommentsAvailable] = React.useState(true);
+
+  //Keeps track of the current comments object in focus so that the application knows which comment to post a reply to
   const [commentObjectInFocus, setCommentObjectInFocus] = useState<
     CommentType | undefined
   >(undefined);
@@ -70,7 +73,7 @@ const MomentCommentsScreen: React.FC<MomentCommentsScreenProps> = ({route}) => {
             objectId={
               commentObjectInFocus ? commentObjectInFocus.comment_id : moment_id
             }
-            isThreadInFocus={commentObjectInFocus ? true : false}
+            isCommentInFocus={commentObjectInFocus ? true : false}
           />
         </View>
       </SafeAreaView>
diff --git a/src/services/CommentService.ts b/src/services/CommentService.ts
new file mode 100644
index 00000000..3baf0305
--- /dev/null
+++ b/src/services/CommentService.ts
@@ -0,0 +1,101 @@
+import AsyncStorage from '@react-native-community/async-storage';
+import {Alert} from 'react-native';
+import {COMMENTS_ENDPOINT, COMMENT_THREAD_ENDPOINT} from '../constants';
+import {ERROR_FAILED_TO_COMMENT} from '../constants/strings';
+import {CommentType} from '../types';
+
+export const getComments = async (
+  objectId: string,
+  fetchThreads: boolean,
+): Promise<CommentType[]> => {
+  let comments: CommentType[] = [];
+  try {
+    const token = await AsyncStorage.getItem('token');
+    const endpoint = fetchThreads
+      ? COMMENT_THREAD_ENDPOINT + '?comment_id='
+      : COMMENTS_ENDPOINT + '?moment_id=';
+    const response = await fetch(endpoint + objectId, {
+      method: 'GET',
+      headers: {
+        Authorization: 'Token ' + token,
+      },
+    });
+    const status = response.status;
+    if (status === 200) {
+      comments = await response.json();
+      console.log(comments[0]);
+    } else {
+      console.log('Could not load comments');
+    }
+  } catch (error) {
+    console.log('Could not load comments', error);
+  }
+  return comments;
+};
+
+export const postComment = async (
+  comment: string,
+  objectId: string,
+  postThread: boolean,
+) => {
+  try {
+    const token = await AsyncStorage.getItem('token');
+    const request = new FormData();
+    request.append('comment', comment);
+    if (postThread) {
+      request.append('comment_id', objectId);
+    } else {
+      request.append('moment_id', objectId);
+    }
+    const endpoint = postThread ? COMMENT_THREAD_ENDPOINT : COMMENTS_ENDPOINT;
+    const response = await fetch(endpoint, {
+      method: 'POST',
+      headers: {
+        Authorization: 'Token ' + token,
+      },
+      body: request,
+    });
+    if (response.status !== 200) {
+      throw 'server error';
+    }
+    return await response.json();
+  } catch (error) {
+    Alert.alert(ERROR_FAILED_TO_COMMENT);
+    return undefined;
+  }
+};
+
+//Get count of comments for a moment
+export const getCommentsCount = async (
+  objectId: string,
+  fetchThread: boolean,
+): Promise<string> => {
+  let comments_count: string = '';
+  try {
+    const token = await AsyncStorage.getItem('token');
+    const endpoint = fetchThread ? COMMENT_THREAD_ENDPOINT : COMMENTS_ENDPOINT;
+    const response = await fetch(endpoint + `${objectId}/`, {
+      method: 'GET',
+      headers: {
+        Authorization: 'Token ' + token,
+      },
+    });
+    const status = response.status;
+    if (status === 200) {
+      const response_data = await response.json();
+      comments_count = response_data.count;
+    } else {
+      console.log(
+        'Something went wrong! 😭',
+        'Not able to retrieve comments count',
+      );
+    }
+  } catch (error) {
+    console.log(
+      'Something went wrong! 😭',
+      'Not able to retrieve comments count',
+      error,
+    );
+  }
+  return comments_count;
+};
diff --git a/src/services/MomentServices.ts b/src/services/MomentServices.ts
index 8399eea3..0110a0d6 100644
--- a/src/services/MomentServices.ts
+++ b/src/services/MomentServices.ts
@@ -1,109 +1,9 @@
-import {CommentType} from './../types/types';
 import AsyncStorage from '@react-native-community/async-storage';
-<<<<<<< Updated upstream
-import {Alert} from 'react-native';
-import RNFetchBlob from 'rn-fetch-blob';
-import {
-  COMMENTS_ENDPOINT,
-  MOMENTS_ENDPOINT,
-  MOMENT_THUMBNAIL_ENDPOINT,
-} from '../constants';
-import {ERROR_FAILED_TO_COMMENT} from '../constants/strings';
-import {MomentType} from '../types';
-import {checkImageUploadStatus} from '../utils';
-
-//Get all comments for a moment
-export const getMomentComments = async (
-  momentId: string,
-): Promise<CommentType[]> => {
-  let comments: CommentType[] = [];
-  try {
-    const token = await AsyncStorage.getItem('token');
-    const response = await fetch(COMMENTS_ENDPOINT + '?moment_id=' + momentId, {
-      method: 'GET',
-      headers: {
-        Authorization: 'Token ' + token,
-      },
-    });
-    const status = response.status;
-    if (status === 200) {
-      comments = await response.json();
-    } else {
-      console.log('Could not load comments');
-    }
-  } catch (error) {
-    console.log('Could not load comments', error);
-  }
-  return comments;
-};
-
-export const postMomentComment = async (
-  commenter: string,
-  comment: string,
-  momentId: string,
-) => {
-  try {
-    const token = await AsyncStorage.getItem('token');
-    const request = new FormData();
-    request.append('moment_id', momentId);
-    request.append('commenter', commenter);
-    request.append('comment', comment);
-    const response = await fetch(COMMENTS_ENDPOINT, {
-      method: 'POST',
-      headers: {
-        Authorization: 'Token ' + token,
-      },
-      body: request,
-    });
-    if (response.status !== 200) {
-      throw 'server error';
-    }
-    return await response.json();
-  } catch (error) {
-    Alert.alert(ERROR_FAILED_TO_COMMENT);
-    return undefined;
-  }
-};
-
-//Get count of comments for a moment
-export const getMomentCommentsCount = async (
-  momentId: string,
-  callback: Function,
-) => {
-  try {
-    const token = await AsyncStorage.getItem('token');
-    const response = await fetch(COMMENTS_ENDPOINT + `${momentId}/`, {
-      method: 'GET',
-      headers: {
-        Authorization: 'Token ' + token,
-      },
-    });
-    const status = response.status;
-    if (status === 200) {
-      const response_data = await response.json();
-      callback(response_data.count);
-    } else {
-      console.log(
-        'Something went wrong! 😭',
-        'Not able to retrieve comments count',
-      );
-    }
-  } catch (error) {
-    console.log(
-      'Something went wrong! 😭',
-      'Not able to retrieve comments count',
-      error,
-    );
-  }
-};
-
-=======
 import RNFetchBlob from 'rn-fetch-blob';
 import {MOMENTS_ENDPOINT, MOMENT_THUMBNAIL_ENDPOINT} from '../constants';
 import {MomentType} from '../types';
 import {checkImageUploadStatus} from '../utils';
 
->>>>>>> Stashed changes
 export const postMoment: (
   fileName: string,
   uri: string,
-- 
cgit v1.2.3-70-g09d2


From 9298f8a31ca25f53d7fb6a0a90af783b9b01f46c Mon Sep 17 00:00:00 2001
From: Ashm Walia <ashmwalia@outlook.com>
Date: Wed, 27 Jan 2021 09:00:16 -0800
Subject: Removed redundancy

---
 src/components/comments/CommentTile.tsx | 6 +++---
 src/constants/constants.ts              | 1 -
 2 files changed, 3 insertions(+), 4 deletions(-)

(limited to 'src/components/comments/CommentTile.tsx')

diff --git a/src/components/comments/CommentTile.tsx b/src/components/comments/CommentTile.tsx
index 9a1607f7..39605f2c 100644
--- a/src/components/comments/CommentTile.tsx
+++ b/src/components/comments/CommentTile.tsx
@@ -4,7 +4,7 @@ import {ProfilePreview} from '../profile';
 import {CommentType, ScreenType, TypeOfComment} from '../../types';
 import {StyleSheet} from 'react-native';
 import ClockIcon from '../../assets/icons/clock-icon-01.svg';
-import {COMMENT_REPLIES} from '../../constants';
+import {TAGG_LIGHT_BLUE} from '../../constants';
 import {TouchableOpacity} from 'react-native-gesture-handler';
 import {getTimePosted, normalize, SCREEN_WIDTH} from '../../utils';
 import Arrow from '../../assets/icons/back-arrow-colored.svg';
@@ -89,7 +89,7 @@ const CommentTile: React.FC<CommentTileProps> = ({
                 <Arrow
                   width={12}
                   height={11}
-                  color={COMMENT_REPLIES}
+                  color={TAGG_LIGHT_BLUE}
                   style={
                     !showReplies
                       ? styles.repliesDownArrow
@@ -164,7 +164,7 @@ const styles = StyleSheet.create({
   },
 
   repliesText: {
-    color: COMMENT_REPLIES,
+    color: TAGG_LIGHT_BLUE,
     fontWeight: '500',
     fontSize: normalize(12),
     marginRight: '3%',
diff --git a/src/constants/constants.ts b/src/constants/constants.ts
index 6a94f51f..ad43c337 100644
--- a/src/constants/constants.ts
+++ b/src/constants/constants.ts
@@ -63,7 +63,6 @@ export const YOUTUBE_FONT_COLOR: string = '#FCA4A4';
 export const TAGG_DARK_BLUE = '#4E699C';
 export const TAGG_LIGHT_BLUE: string = '#698DD3';
 export const TAGG_LIGHT_PURPLE = '#F4DDFF';
-export const COMMENT_REPLIES = '#698DD3';
 
 export const TAGGS_GRADIENT = {
   start: '#9F00FF',
-- 
cgit v1.2.3-70-g09d2


From 3cbfdc6026ef886b7919181b69a2f252723a6bd8 Mon Sep 17 00:00:00 2001
From: Ivan Chen <ivan@tagg.id>
Date: Wed, 27 Jan 2021 14:18:00 -0500
Subject: Squashed commit of the following:

commit 9298f8a31ca25f53d7fb6a0a90af783b9b01f46c
Author: Ashm Walia <ashmwalia@outlook.com>
Date:   Wed Jan 27 09:00:16 2021 -0800

    Removed redundancy

commit 2a93a92521d989664ebb8dfebe011d8df67ad40f
Author: Ashm Walia <ashmwalia@outlook.com>
Date:   Wed Jan 27 08:58:24 2021 -0800

    Sc

commit 2f5f9df6dec1e905f3abf37d124ecd92d0e3a3d9
Author: Ashm Walia <ashmwalia@outlook.com>
Date:   Wed Jan 27 08:29:56 2021 -0800

    Pre-final

commit 85c0f668665696ba8127ee1ea436d10ec0af955f
Author: Ashm Walia <ashmwalia@outlook.com>
Date:   Wed Jan 27 08:24:43 2021 -0800

    Pre-final

commit 755f4f540d3e759ff9ad3bc35c64b6f7fc83998b
Author: Ashm Walia <ashmwalia@outlook.com>
Date:   Mon Jan 25 18:00:44 2021 -0800

    Add provision to show and hide replies
---
 src/assets/icons/back-arrow-colored.svg       |   1 +
 src/components/comments/AddComment.tsx        |  45 ++++---
 src/components/comments/CommentTile.tsx       | 161 ++++++++++++++++++++++----
 src/components/comments/CommentsContainer.tsx |  97 ++++++++++++++++
 src/components/moments/MomentPostContent.tsx  |   8 +-
 src/constants/api.ts                          |   1 +
 src/constants/strings.ts                      |   2 +
 src/screens/profile/MomentCommentsScreen.tsx  |  81 ++++++-------
 src/services/CommentService.ts                | 101 ++++++++++++++++
 src/services/MomentServices.ts                |  93 +--------------
 src/services/index.ts                         |   1 +
 src/types/types.ts                            |   3 +
 12 files changed, 413 insertions(+), 181 deletions(-)
 create mode 100644 src/assets/icons/back-arrow-colored.svg
 create mode 100644 src/components/comments/CommentsContainer.tsx
 create mode 100644 src/services/CommentService.ts

(limited to 'src/components/comments/CommentTile.tsx')

diff --git a/src/assets/icons/back-arrow-colored.svg b/src/assets/icons/back-arrow-colored.svg
new file mode 100644
index 00000000..123426d7
--- /dev/null
+++ b/src/assets/icons/back-arrow-colored.svg
@@ -0,0 +1 @@
+<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 385.86 696.76"><defs><style>.cls-1{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:77.17px;}</style></defs><polyline class="cls-1" points="347.28 38.58 38.58 351.69 347.28 658.17"/></svg>
\ No newline at end of file
diff --git a/src/components/comments/AddComment.tsx b/src/components/comments/AddComment.tsx
index 24b3473c..46086e81 100644
--- a/src/components/comments/AddComment.tsx
+++ b/src/components/comments/AddComment.tsx
@@ -1,4 +1,4 @@
-import React, {useEffect} from 'react';
+import React, {useEffect, useRef} from 'react';
 import {
   Image,
   Keyboard,
@@ -11,7 +11,7 @@ import {TextInput, TouchableOpacity} from 'react-native-gesture-handler';
 import {useSelector} from 'react-redux';
 import UpArrowIcon from '../../assets/icons/up_arrow.svg';
 import {TAGG_LIGHT_BLUE} from '../../constants';
-import {postMomentComment} from '../../services';
+import {postComment} from '../../services';
 import {RootState} from '../../store/rootreducer';
 import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils';
 
@@ -23,26 +23,27 @@ import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils';
 
 export interface AddCommentProps {
   setNewCommentsAvailable: Function;
-  moment_id: string;
+  objectId: string;
+  placeholderText: string;
+  isCommentInFocus: boolean;
 }
 
 const AddComment: React.FC<AddCommentProps> = ({
   setNewCommentsAvailable,
-  moment_id,
+  objectId,
+  placeholderText,
+  isCommentInFocus,
 }) => {
   const [comment, setComment] = React.useState('');
   const [keyboardVisible, setKeyboardVisible] = React.useState(false);
 
-  const {
-    avatar,
-    user: {userId},
-  } = useSelector((state: RootState) => state.user);
+  const {avatar} = useSelector((state: RootState) => state.user);
 
-  const postComment = async () => {
-    const postedComment = await postMomentComment(
-      userId,
+  const addComment = async () => {
+    const postedComment = await postComment(
       comment.trim(),
-      moment_id,
+      objectId,
+      isCommentInFocus,
     );
 
     if (postedComment) {
@@ -63,6 +64,15 @@ const AddComment: React.FC<AddCommentProps> = ({
     return () => Keyboard.removeListener('keyboardWillHide', hideKeyboard);
   }, []);
 
+  const ref = useRef<TextInput>(null);
+
+  //If a comment is in Focus, bring the keyboard up so user is able to type in a reply
+  useEffect(() => {
+    if (isCommentInFocus) {
+      ref.current?.focus();
+    }
+  }, [isCommentInFocus]);
+
   return (
     <KeyboardAvoidingView
       behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
@@ -70,7 +80,7 @@ const AddComment: React.FC<AddCommentProps> = ({
       <View
         style={[
           styles.container,
-          keyboardVisible ? {backgroundColor: '#fff'} : {},
+          keyboardVisible ? styles.whiteBackround : {},
         ]}>
         <View style={styles.textContainer}>
           <Image
@@ -83,15 +93,16 @@ const AddComment: React.FC<AddCommentProps> = ({
           />
           <TextInput
             style={styles.text}
-            placeholder="Add a comment..."
+            placeholder={placeholderText}
             placeholderTextColor="grey"
             onChangeText={setComment}
             value={comment}
             autoCorrect={false}
             multiline={true}
+            ref={ref}
           />
           <View style={styles.submitButton}>
-            <TouchableOpacity style={styles.submitButton} onPress={postComment}>
+            <TouchableOpacity style={styles.submitButton} onPress={addComment}>
               <UpArrowIcon width={35} height={35} color={'white'} />
             </TouchableOpacity>
           </View>
@@ -100,6 +111,7 @@ const AddComment: React.FC<AddCommentProps> = ({
     </KeyboardAvoidingView>
   );
 };
+
 const styles = StyleSheet.create({
   container: {
     backgroundColor: '#f7f7f7',
@@ -140,6 +152,9 @@ const styles = StyleSheet.create({
     marginVertical: '2%',
     alignSelf: 'flex-end',
   },
+  whiteBackround: {
+    backgroundColor: '#fff',
+  },
 });
 
 export default AddComment;
diff --git a/src/components/comments/CommentTile.tsx b/src/components/comments/CommentTile.tsx
index 47f25a53..39605f2c 100644
--- a/src/components/comments/CommentTile.tsx
+++ b/src/components/comments/CommentTile.tsx
@@ -1,10 +1,14 @@
-import React from 'react';
+import React, {useState} from 'react';
 import {Text, View} from 'react-native-animatable';
 import {ProfilePreview} from '../profile';
-import {CommentType, ScreenType} from '../../types';
+import {CommentType, ScreenType, TypeOfComment} from '../../types';
 import {StyleSheet} from 'react-native';
-import {getTimePosted} from '../../utils';
 import ClockIcon from '../../assets/icons/clock-icon-01.svg';
+import {TAGG_LIGHT_BLUE} from '../../constants';
+import {TouchableOpacity} from 'react-native-gesture-handler';
+import {getTimePosted, normalize, SCREEN_WIDTH} from '../../utils';
+import Arrow from '../../assets/icons/back-arrow-colored.svg';
+import CommentsContainer from './CommentsContainer';
 
 /**
  * Displays users's profile picture, comment posted by them and the time difference between now and when a comment was posted.
@@ -13,54 +17,132 @@ import ClockIcon from '../../assets/icons/clock-icon-01.svg';
 interface CommentTileProps {
   comment_object: CommentType;
   screenType: ScreenType;
+  typeOfComment: TypeOfComment;
+  setCommentObjectInFocus?: (comment: CommentType | undefined) => void;
 }
 
 const CommentTile: React.FC<CommentTileProps> = ({
   comment_object,
   screenType,
+  typeOfComment,
+  setCommentObjectInFocus,
 }) => {
   const timePosted = getTimePosted(comment_object.date_created);
+  const [showReplies, setShowReplies] = useState<boolean>(false);
+
+  /**
+   * Case : A COMMENT IS IN FOCUS && REPLY SECTION IS HIDDEN
+   *     Bring the current comment to focus
+   * Case : No COMMENT IS IN FOCUS && REPLY SECTION IS SHOWN
+   *     Unfocus comment in focus
+   * In any case toggle value of showReplies
+   */
+  const toggleReplies = () => {
+    if (setCommentObjectInFocus) {
+      if (!showReplies) {
+        setCommentObjectInFocus(comment_object);
+      } else {
+        setCommentObjectInFocus(undefined);
+      }
+    }
+    setShowReplies(!showReplies);
+  };
+
+  /**
+   * Method to compute text to be shown for replies button
+   */
+  const getRepliesText = () =>
+    showReplies
+      ? 'Hide'
+      : comment_object.replies_count > 0
+      ? `Replies (${comment_object.replies_count})`
+      : 'Replies';
+
   return (
-    <View style={styles.container}>
-      <ProfilePreview
-        profilePreview={{
-          id: comment_object.commenter.id,
-          username: comment_object.commenter.username,
-          first_name: comment_object.commenter.first_name,
-          last_name: comment_object.commenter.last_name,
-        }}
-        previewType={'Comment'}
-        screenType={screenType}
-      />
-      <View style={styles.body}>
-        <Text style={styles.comment}>{comment_object.comment}</Text>
-        <View style={styles.clockIconAndTime}>
-          <ClockIcon style={styles.clockIcon} />
-          <Text style={styles.date_time}>{' ' + timePosted}</Text>
-        </View>
+    <>
+      <View
+        style={[
+          styles.container,
+          typeOfComment === 'Thread' ? styles.moreMarginWithThread : {},
+        ]}>
+        <ProfilePreview
+          profilePreview={{
+            id: comment_object.commenter.id,
+            username: comment_object.commenter.username,
+            first_name: comment_object.commenter.first_name,
+            last_name: comment_object.commenter.last_name,
+          }}
+          previewType={'Comment'}
+          screenType={screenType}
+        />
+        <TouchableOpacity style={styles.body} onPress={toggleReplies}>
+          <Text style={styles.comment}>{comment_object.comment}</Text>
+          <View style={styles.clockIconAndTime}>
+            <ClockIcon style={styles.clockIcon} />
+            <Text style={styles.date_time}>{' ' + timePosted}</Text>
+            <View style={styles.flexer} />
+
+            {/*** Show replies text only if there are some replies present */}
+            {typeOfComment === 'Comment' && comment_object.replies_count > 0 && (
+              <View style={styles.repliesTextAndIconContainer}>
+                <Text style={styles.repliesText}>{getRepliesText()}</Text>
+                <Arrow
+                  width={12}
+                  height={11}
+                  color={TAGG_LIGHT_BLUE}
+                  style={
+                    !showReplies
+                      ? styles.repliesDownArrow
+                      : styles.repliesUpArrow
+                  }
+                />
+              </View>
+            )}
+          </View>
+        </TouchableOpacity>
       </View>
-    </View>
+
+      {/*** Show replies if toggle state is true */}
+      {showReplies && (
+        <View
+          style={{
+            width: SCREEN_WIDTH,
+          }}>
+          <CommentsContainer
+            objectId={comment_object.comment_id}
+            screenType={screenType}
+            setNewCommentsAvailable={() => {}}
+            newCommentsAvailable={true}
+            typeOfComment={'Thread'}
+          />
+        </View>
+      )}
+    </>
   );
 };
 
 const styles = StyleSheet.create({
   container: {
-    marginLeft: '3%',
-    marginRight: '3%',
+    marginHorizontal: '3%',
     borderBottomWidth: 1,
     borderColor: 'lightgray',
     marginBottom: '3%',
+    flexDirection: 'column',
+    flex: 1,
+  },
+  moreMarginWithThread: {
+    marginHorizontal: '7%',
   },
   body: {
     marginLeft: 56,
   },
   comment: {
-    position: 'relative',
-    top: -5,
     marginBottom: '2%',
+    top: -5,
   },
   date_time: {
     color: 'gray',
+    fontSize: normalize(12),
   },
   clockIcon: {
     width: 12,
@@ -71,6 +153,35 @@ const styles = StyleSheet.create({
     flexDirection: 'row',
     marginBottom: '3%',
   },
+
+  flexer: {
+    flex: 1,
+  },
+
+  repliesTextAndIconContainer: {
+    flexDirection: 'row',
+    alignItems: 'center',
+  },
+
+  repliesText: {
+    color: TAGG_LIGHT_BLUE,
+    fontWeight: '500',
+    fontSize: normalize(12),
+    marginRight: '3%',
+  },
+  repliesBody: {
+    width: SCREEN_WIDTH,
+  },
+
+  repliesDownArrow: {
+    transform: [{rotate: '270deg'}],
+    marginTop: '7%',
+  },
+
+  repliesUpArrow: {
+    transform: [{rotate: '90deg'}],
+    marginTop: '7%',
+  },
 });
 
 export default CommentTile;
diff --git a/src/components/comments/CommentsContainer.tsx b/src/components/comments/CommentsContainer.tsx
new file mode 100644
index 00000000..0a19694b
--- /dev/null
+++ b/src/components/comments/CommentsContainer.tsx
@@ -0,0 +1,97 @@
+import React, {useRef, useEffect, useState} from 'react';
+import {StyleSheet} from 'react-native';
+import {ScrollView} from 'react-native-gesture-handler';
+import {useDispatch} from 'react-redux';
+import {CommentTile} from '.';
+import {getComments} from '../../services';
+import {CommentType, ScreenType, TypeOfComment} from '../../types';
+export type CommentsContainerProps = {
+  screenType: ScreenType;
+
+  //objectId can be either moment_id or comment_id
+  objectId: string;
+  setCommentsLength?: (count: number) => void;
+  newCommentsAvailable: boolean;
+  setNewCommentsAvailable: (value: boolean) => void;
+  typeOfComment: TypeOfComment;
+  setCommentObjectInFocus?: (comment: CommentType | undefined) => void;
+  commentObjectInFocus?: CommentType;
+};
+
+/**
+ * Comments Container to be used for both comments and replies
+ */
+
+const CommentsContainer: React.FC<CommentsContainerProps> = ({
+  screenType,
+  objectId,
+  setCommentsLength,
+  newCommentsAvailable,
+  setNewCommentsAvailable,
+  typeOfComment,
+  setCommentObjectInFocus,
+  commentObjectInFocus,
+}) => {
+  const [commentsList, setCommentsList] = useState<CommentType[]>([]);
+  const dispatch = useDispatch();
+  const ref = useRef<ScrollView>(null);
+
+  useEffect(() => {
+    //Scroll only if a new comment and not a reply was posted
+    const shouldScroll = () =>
+      typeOfComment === 'Comment' && !commentObjectInFocus;
+    const loadComments = async () => {
+      const comments = await getComments(objectId, typeOfComment === 'Thread');
+      setCommentsList(comments);
+      if (setCommentsLength) {
+        setCommentsLength(comments.length);
+      }
+      setNewCommentsAvailable(false);
+    };
+    if (newCommentsAvailable) {
+      loadComments();
+      if (shouldScroll()) {
+        setTimeout(() => {
+          ref.current?.scrollToEnd();
+        }, 500);
+      }
+    }
+  }, [
+    dispatch,
+    objectId,
+    newCommentsAvailable,
+    setNewCommentsAvailable,
+    setCommentsLength,
+    typeOfComment,
+    commentObjectInFocus,
+  ]);
+
+  return (
+    <ScrollView
+      ref={ref}
+      style={styles.scrollView}
+      contentContainerStyle={styles.scrollViewContent}>
+      {commentsList &&
+        commentsList.map((comment: CommentType) => (
+          <CommentTile
+            key={comment.comment_id}
+            comment_object={comment}
+            screenType={screenType}
+            typeOfComment={typeOfComment}
+            setCommentObjectInFocus={setCommentObjectInFocus}
+          />
+        ))}
+    </ScrollView>
+  );
+};
+
+const styles = StyleSheet.create({
+  scrollView: {
+    paddingHorizontal: 20,
+  },
+  scrollViewContent: {
+    justifyContent: 'center',
+  },
+});
+
+export default CommentsContainer;
diff --git a/src/components/moments/MomentPostContent.tsx b/src/components/moments/MomentPostContent.tsx
index 508b6d9f..d68ceaa3 100644
--- a/src/components/moments/MomentPostContent.tsx
+++ b/src/components/moments/MomentPostContent.tsx
@@ -1,6 +1,6 @@
 import React, {useEffect} from 'react';
 import {Image, StyleSheet, Text, View, ViewProps} from 'react-native';
-import {getMomentCommentsCount} from '../../services';
+import {getCommentsCount} from '../../services';
 import {ScreenType} from '../../types';
 import {getTimePosted, SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils';
 import {CommentsCount} from '../comments';
@@ -24,8 +24,12 @@ const MomentPostContent: React.FC<MomentPostContentProps> = ({
   const [comments_count, setCommentsCount] = React.useState('');
 
   useEffect(() => {
+    const fetchCommentsCount = async () => {
+      const count = await getCommentsCount(momentId, false);
+      setCommentsCount(count);
+    };
     setElapsedTime(getTimePosted(dateTime));
-    getMomentCommentsCount(momentId, setCommentsCount);
+    fetchCommentsCount();
   }, [dateTime, momentId]);
 
   return (
diff --git a/src/constants/api.ts b/src/constants/api.ts
index 701070eb..32631be0 100644
--- a/src/constants/api.ts
+++ b/src/constants/api.ts
@@ -30,6 +30,7 @@ export const MOMENT_CATEGORY_ENDPOINT: string = API_URL + 'moment-category/';
 export const NOTIFICATIONS_ENDPOINT: string = API_URL + 'notifications/';
 export const DISCOVER_ENDPOINT: string = API_URL + 'discover/';
 export const WAITLIST_USER_ENDPOINT: string = API_URL + 'waitlist-user/';
+export const COMMENT_THREAD_ENDPOINT: string = API_URL + 'reply/';
 
 // Register as FCM device
 export const FCM_ENDPOINT: string = API_URL + 'fcm/';
diff --git a/src/constants/strings.ts b/src/constants/strings.ts
index a1793658..77ded7be 100644
--- a/src/constants/strings.ts
+++ b/src/constants/strings.ts
@@ -1,7 +1,9 @@
+
 /* eslint-disable */
 // Below is the regex to convert this into a csv for the Google Sheet
 // export const (.*) = .*?(['|"|`])(.*)\2;
 // replace with: $1\t$3
+export const ADD_COMMENT_TEXT = (username?: string) => username ? `Reply to ${username}` : 'Add a comment...'
 export const COMING_SOON_MSG = 'Creating more fun things for you, surprises coming soon 😉';
 export const ERROR_AUTHENTICATION = 'An error occurred during authentication. Please login again!';
 export const ERROR_CATEGORY_CREATION = 'There was a problem creating your categories. Please refresh and try again.';
diff --git a/src/screens/profile/MomentCommentsScreen.tsx b/src/screens/profile/MomentCommentsScreen.tsx
index 2bceafc9..58422f0f 100644
--- a/src/screens/profile/MomentCommentsScreen.tsx
+++ b/src/screens/profile/MomentCommentsScreen.tsx
@@ -1,19 +1,13 @@
 import {RouteProp, useNavigation} from '@react-navigation/native';
-import React, {useEffect, useRef} from 'react';
-import {
-  ScrollView,
-  StyleSheet,
-  Text,
-  TouchableOpacity,
-  View,
-} from 'react-native';
+import React, {useState} from 'react';
+import {StyleSheet, Text, TouchableOpacity, View} from 'react-native';
 import {SafeAreaView} from 'react-native-safe-area-context';
-import {useDispatch} from 'react-redux';
-import {getMomentComments} from '../..//services';
 import BackIcon from '../../assets/icons/back-arrow.svg';
-import {CommentTile, TabsGradient} from '../../components';
+import {TabsGradient} from '../../components';
 import {AddComment} from '../../components/';
-import {ProfileStackParams} from '../../routes/main';
+import CommentsContainer from '../../components/comments/CommentsContainer';
+import {ADD_COMMENT_TEXT} from '../../constants/strings';
+import {MainStackParams} from '../../routes/main';
 import {CommentType} from '../../types';
 import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils';
 
@@ -24,7 +18,7 @@ import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils';
  */
 
 type MomentCommentsScreenRouteProps = RouteProp<
-  ProfileStackParams,
+  MainStackParams,
   'MomentCommentsScreen'
 >;
 
@@ -35,25 +29,15 @@ interface MomentCommentsScreenProps {
 const MomentCommentsScreen: React.FC<MomentCommentsScreenProps> = ({route}) => {
   const navigation = useNavigation();
   const {moment_id, screenType} = route.params;
-  const [commentsList, setCommentsList] = React.useState([]);
+
+  //Receives comment length from child CommentsContainer
+  const [commentsLength, setCommentsLength] = useState<number>(0);
   const [newCommentsAvailable, setNewCommentsAvailable] = React.useState(true);
-  const dispatch = useDispatch();
-  const ref = useRef<ScrollView>(null);
 
-  useEffect(() => {
-    const loadComments = async () => {
-      getMomentComments(moment_id, setCommentsList);
-      setNewCommentsAvailable(false);
-    };
-    if (newCommentsAvailable) {
-      loadComments();
-      setTimeout(() => {
-        ref.current?.scrollToEnd({
-          animated: true,
-        });
-      }, 500);
-    }
-  }, [dispatch, moment_id, newCommentsAvailable]);
+  //Keeps track of the current comments object in focus so that the application knows which comment to post a reply to
+  const [commentObjectInFocus, setCommentObjectInFocus] = useState<
+    CommentType | undefined
+  >(undefined);
 
   return (
     <View style={styles.background}>
@@ -66,27 +50,30 @@ const MomentCommentsScreen: React.FC<MomentCommentsScreenProps> = ({route}) => {
             }}>
             <BackIcon height={'100%'} width={'100%'} color={'white'} />
           </TouchableOpacity>
-          <Text style={styles.headerText}>
-            {commentsList.length + ' Comments'}
-          </Text>
+          <Text style={styles.headerText}>{commentsLength + ' Comments'}</Text>
         </View>
         <View style={styles.body}>
-          <ScrollView
-            ref={ref}
-            style={styles.scrollView}
-            contentContainerStyle={styles.scrollViewContent}>
-            {commentsList &&
-              commentsList.map((comment: CommentType) => (
-                <CommentTile
-                  key={comment.comment_id}
-                  comment_object={comment}
-                  screenType={screenType}
-                />
-              ))}
-          </ScrollView>
+          <CommentsContainer
+            objectId={moment_id}
+            screenType={screenType}
+            setCommentsLength={setCommentsLength}
+            newCommentsAvailable={newCommentsAvailable}
+            setNewCommentsAvailable={setNewCommentsAvailable}
+            setCommentObjectInFocus={setCommentObjectInFocus}
+            commentObjectInFocus={commentObjectInFocus}
+            typeOfComment={'Comment'}
+          />
           <AddComment
+            placeholderText={
+              commentObjectInFocus
+                ? ADD_COMMENT_TEXT(commentObjectInFocus.commenter.username)
+                : ADD_COMMENT_TEXT()
+            }
             setNewCommentsAvailable={setNewCommentsAvailable}
-            moment_id={moment_id}
+            objectId={
+              commentObjectInFocus ? commentObjectInFocus.comment_id : moment_id
+            }
+            isCommentInFocus={commentObjectInFocus ? true : false}
           />
         </View>
       </SafeAreaView>
diff --git a/src/services/CommentService.ts b/src/services/CommentService.ts
new file mode 100644
index 00000000..3baf0305
--- /dev/null
+++ b/src/services/CommentService.ts
@@ -0,0 +1,101 @@
+import AsyncStorage from '@react-native-community/async-storage';
+import {Alert} from 'react-native';
+import {COMMENTS_ENDPOINT, COMMENT_THREAD_ENDPOINT} from '../constants';
+import {ERROR_FAILED_TO_COMMENT} from '../constants/strings';
+import {CommentType} from '../types';
+
+export const getComments = async (
+  objectId: string,
+  fetchThreads: boolean,
+): Promise<CommentType[]> => {
+  let comments: CommentType[] = [];
+  try {
+    const token = await AsyncStorage.getItem('token');
+    const endpoint = fetchThreads
+      ? COMMENT_THREAD_ENDPOINT + '?comment_id='
+      : COMMENTS_ENDPOINT + '?moment_id=';
+    const response = await fetch(endpoint + objectId, {
+      method: 'GET',
+      headers: {
+        Authorization: 'Token ' + token,
+      },
+    });
+    const status = response.status;
+    if (status === 200) {
+      comments = await response.json();
+      console.log(comments[0]);
+    } else {
+      console.log('Could not load comments');
+    }
+  } catch (error) {
+    console.log('Could not load comments', error);
+  }
+  return comments;
+};
+
+export const postComment = async (
+  comment: string,
+  objectId: string,
+  postThread: boolean,
+) => {
+  try {
+    const token = await AsyncStorage.getItem('token');
+    const request = new FormData();
+    request.append('comment', comment);
+    if (postThread) {
+      request.append('comment_id', objectId);
+    } else {
+      request.append('moment_id', objectId);
+    }
+    const endpoint = postThread ? COMMENT_THREAD_ENDPOINT : COMMENTS_ENDPOINT;
+    const response = await fetch(endpoint, {
+      method: 'POST',
+      headers: {
+        Authorization: 'Token ' + token,
+      },
+      body: request,
+    });
+    if (response.status !== 200) {
+      throw 'server error';
+    }
+    return await response.json();
+  } catch (error) {
+    Alert.alert(ERROR_FAILED_TO_COMMENT);
+    return undefined;
+  }
+};
+
+//Get count of comments for a moment
+export const getCommentsCount = async (
+  objectId: string,
+  fetchThread: boolean,
+): Promise<string> => {
+  let comments_count: string = '';
+  try {
+    const token = await AsyncStorage.getItem('token');
+    const endpoint = fetchThread ? COMMENT_THREAD_ENDPOINT : COMMENTS_ENDPOINT;
+    const response = await fetch(endpoint + `${objectId}/`, {
+      method: 'GET',
+      headers: {
+        Authorization: 'Token ' + token,
+      },
+    });
+    const status = response.status;
+    if (status === 200) {
+      const response_data = await response.json();
+      comments_count = response_data.count;
+    } else {
+      console.log(
+        'Something went wrong! 😭',
+        'Not able to retrieve comments count',
+      );
+    }
+  } catch (error) {
+    console.log(
+      'Something went wrong! 😭',
+      'Not able to retrieve comments count',
+      error,
+    );
+  }
+  return comments_count;
+};
diff --git a/src/services/MomentServices.ts b/src/services/MomentServices.ts
index 7bad6d4c..0110a0d6 100644
--- a/src/services/MomentServices.ts
+++ b/src/services/MomentServices.ts
@@ -1,100 +1,9 @@
 import AsyncStorage from '@react-native-community/async-storage';
-import {Alert} from 'react-native';
 import RNFetchBlob from 'rn-fetch-blob';
-import {
-  COMMENTS_ENDPOINT,
-  MOMENTS_ENDPOINT,
-  MOMENT_THUMBNAIL_ENDPOINT,
-} from '../constants';
-import {ERROR_FAILED_TO_COMMENT} from '../constants/strings';
+import {MOMENTS_ENDPOINT, MOMENT_THUMBNAIL_ENDPOINT} from '../constants';
 import {MomentType} from '../types';
 import {checkImageUploadStatus} from '../utils';
 
-//Get all comments for a moment
-export const getMomentComments = async (
-  momentId: string,
-  callback: Function,
-) => {
-  try {
-    const token = await AsyncStorage.getItem('token');
-    const response = await fetch(COMMENTS_ENDPOINT + '?moment_id=' + momentId, {
-      method: 'GET',
-      headers: {
-        Authorization: 'Token ' + token,
-      },
-    });
-    const status = response.status;
-    if (status === 200) {
-      const comments = await response.json();
-      callback(comments);
-    } else {
-      console.log('Could not load comments');
-    }
-  } catch (error) {
-    console.log('Could not load comments', error);
-  }
-};
-
-export const postMomentComment = async (
-  commenter: string,
-  comment: string,
-  momentId: string,
-) => {
-  try {
-    const token = await AsyncStorage.getItem('token');
-    const request = new FormData();
-    request.append('moment_id', momentId);
-    request.append('commenter', commenter);
-    request.append('comment', comment);
-    const response = await fetch(COMMENTS_ENDPOINT, {
-      method: 'POST',
-      headers: {
-        Authorization: 'Token ' + token,
-      },
-      body: request,
-    });
-    if (response.status !== 200) {
-      throw 'server error';
-    }
-    return await response.json();
-  } catch (error) {
-    Alert.alert(ERROR_FAILED_TO_COMMENT);
-    return undefined;
-  }
-};
-
-//Get count of comments for a moment
-export const getMomentCommentsCount = async (
-  momentId: string,
-  callback: Function,
-) => {
-  try {
-    const token = await AsyncStorage.getItem('token');
-    const response = await fetch(COMMENTS_ENDPOINT + `${momentId}/`, {
-      method: 'GET',
-      headers: {
-        Authorization: 'Token ' + token,
-      },
-    });
-    const status = response.status;
-    if (status === 200) {
-      const response_data = await response.json();
-      callback(response_data.count);
-    } else {
-      console.log(
-        'Something went wrong! 😭',
-        'Not able to retrieve comments count',
-      );
-    }
-  } catch (error) {
-    console.log(
-      'Something went wrong! 😭',
-      'Not able to retrieve comments count',
-      error,
-    );
-  }
-};
-
 export const postMoment: (
   fileName: string,
   uri: string,
diff --git a/src/services/index.ts b/src/services/index.ts
index 56cefddd..f558247f 100644
--- a/src/services/index.ts
+++ b/src/services/index.ts
@@ -9,3 +9,4 @@ export * from './MomentCategoryService';
 export * from './NotificationService';
 export * from './FCMService';
 export * from './WaitlistUserService';
+export * from './CommentService';
diff --git a/src/types/types.ts b/src/types/types.ts
index d9d0b56b..0c0f9d8b 100644
--- a/src/types/types.ts
+++ b/src/types/types.ts
@@ -91,6 +91,7 @@ export interface CommentType {
   comment: string;
   date_created: string;
   moment_id: string;
+  replies_count: number;
   commenter: ProfilePreviewType;
 }
 
@@ -174,3 +175,5 @@ export type NotificationType = {
   timestamp: string;
   unread: boolean;
 };
+
+export type TypeOfComment = 'Comment' | 'Thread';
-- 
cgit v1.2.3-70-g09d2


From fb69ccebb05d2ec54d85576d23989e7309349830 Mon Sep 17 00:00:00 2001
From: Ivan Chen <ivan@tagg.id>
Date: Wed, 27 Jan 2021 16:15:00 -0500
Subject: finished delete

---
 src/assets/ionicons/trash-outline.svg         |   1 +
 src/components/comments/CommentTile.tsx       | 115 +++++++++++++++++++-------
 src/components/comments/CommentsContainer.tsx |  14 ++--
 src/constants/strings.ts                      |   2 +-
 src/services/CommentService.ts                |  18 ++++
 5 files changed, 114 insertions(+), 36 deletions(-)
 create mode 100644 src/assets/ionicons/trash-outline.svg

(limited to 'src/components/comments/CommentTile.tsx')

diff --git a/src/assets/ionicons/trash-outline.svg b/src/assets/ionicons/trash-outline.svg
new file mode 100644
index 00000000..4920b56a
--- /dev/null
+++ b/src/assets/ionicons/trash-outline.svg
@@ -0,0 +1 @@
+<svg xmlns='http://www.w3.org/2000/svg' class='ionicon' viewBox='0 0 512 512'><title>Trash</title><path d='M112 112l20 320c.95 18.49 14.4 32 32 32h184c17.67 0 30.87-13.51 32-32l20-320' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='32'/><path stroke='currentColor' stroke-linecap='round' stroke-miterlimit='10' stroke-width='32' d='M80 112h352'/><path d='M192 112V72h0a23.93 23.93 0 0124-24h80a23.93 23.93 0 0124 24h0v40M256 176v224M184 176l8 224M328 176l-8 224' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='32'/></svg>
\ No newline at end of file
diff --git a/src/components/comments/CommentTile.tsx b/src/components/comments/CommentTile.tsx
index 39605f2c..e12276a9 100644
--- a/src/components/comments/CommentTile.tsx
+++ b/src/components/comments/CommentTile.tsx
@@ -1,14 +1,18 @@
-import React, {useState} from 'react';
+import React, {Fragment, useRef, useState} from 'react';
 import {Text, View} from 'react-native-animatable';
 import {ProfilePreview} from '../profile';
 import {CommentType, ScreenType, TypeOfComment} from '../../types';
-import {StyleSheet} from 'react-native';
+import {Alert, Animated, StyleSheet} from 'react-native';
 import ClockIcon from '../../assets/icons/clock-icon-01.svg';
 import {TAGG_LIGHT_BLUE} from '../../constants';
-import {TouchableOpacity} from 'react-native-gesture-handler';
+import {RectButton, TouchableOpacity} from 'react-native-gesture-handler';
 import {getTimePosted, normalize, SCREEN_WIDTH} from '../../utils';
 import Arrow from '../../assets/icons/back-arrow-colored.svg';
+import Trash from '../../assets/ionicons/trash-outline.svg';
 import CommentsContainer from './CommentsContainer';
+import Swipeable from 'react-native-gesture-handler/Swipeable';
+import {deleteComment} from '../../services';
+import {ERROR_FAILED_TO_DELETE_COMMENT} from '../../constants/strings';
 
 /**
  * Displays users's profile picture, comment posted by them and the time difference between now and when a comment was posted.
@@ -19,6 +23,8 @@ interface CommentTileProps {
   screenType: ScreenType;
   typeOfComment: TypeOfComment;
   setCommentObjectInFocus?: (comment: CommentType | undefined) => void;
+  setNewCommentsAvailable: (available: boolean) => void;
+  canDelete: boolean;
 }
 
 const CommentTile: React.FC<CommentTileProps> = ({
@@ -26,9 +32,13 @@ const CommentTile: React.FC<CommentTileProps> = ({
   screenType,
   typeOfComment,
   setCommentObjectInFocus,
+  setNewCommentsAvailable,
+  canDelete,
 }) => {
   const timePosted = getTimePosted(comment_object.date_created);
   const [showReplies, setShowReplies] = useState<boolean>(false);
+  const swipeRef = useRef<Swipeable>(null);
+  const isThread = typeOfComment === 'Thread';
 
   /**
    * Case : A COMMENT IS IN FOCUS && REPLY SECTION IS HIDDEN
@@ -58,13 +68,46 @@ const CommentTile: React.FC<CommentTileProps> = ({
       ? `Replies (${comment_object.replies_count})`
       : 'Replies';
 
+  const renderRightAction = (text: string, color: string, progress) => {
+    const pressHandler = async () => {
+      swipeRef.current?.close();
+      const success = await deleteComment(comment_object.comment_id, isThread);
+      if (success) {
+        setNewCommentsAvailable(true);
+      } else {
+        Alert.alert(ERROR_FAILED_TO_DELETE_COMMENT);
+      }
+    };
+    return (
+      <Animated.View>
+        <RectButton
+          style={[styles.rightAction, {backgroundColor: color}]}
+          onPress={pressHandler}>
+          <Trash width={normalize(25)} height={normalize(25)} color={'white'} />
+          <Text style={styles.actionText}>{text}</Text>
+        </RectButton>
+      </Animated.View>
+    );
+  };
+
+  const renderRightActions = (progress) =>
+    canDelete ? (
+      <View style={styles.swipeActions}>
+        {renderRightAction('Delete', '#c42634', progress)}
+      </View>
+    ) : (
+      <Fragment />
+    );
+
   return (
-    <>
+    <Swipeable
+      ref={swipeRef}
+      renderRightActions={renderRightActions}
+      rightThreshold={40}
+      friction={2}
+      containerStyle={styles.swipableContainer}>
       <View
-        style={[
-          styles.container,
-          typeOfComment === 'Thread' ? styles.moreMarginWithThread : {},
-        ]}>
+        style={[styles.container, isThread ? styles.moreMarginWithThread : {}]}>
         <ProfilePreview
           profilePreview={{
             id: comment_object.commenter.id,
@@ -104,40 +147,40 @@ const CommentTile: React.FC<CommentTileProps> = ({
 
       {/*** Show replies if toggle state is true */}
       {showReplies && (
-        <View
-          style={{
-            width: SCREEN_WIDTH,
-          }}>
-          <CommentsContainer
-            objectId={comment_object.comment_id}
-            screenType={screenType}
-            setNewCommentsAvailable={() => {}}
-            newCommentsAvailable={true}
-            typeOfComment={'Thread'}
-          />
-        </View>
+        <CommentsContainer
+          objectId={comment_object.comment_id}
+          screenType={screenType}
+          setNewCommentsAvailable={() => {}}
+          newCommentsAvailable={true}
+          typeOfComment={'Thread'}
+        />
       )}
-    </>
+    </Swipeable>
   );
 };
 
 const styles = StyleSheet.create({
   container: {
-    marginHorizontal: '3%',
     borderBottomWidth: 1,
     borderColor: 'lightgray',
-    marginBottom: '3%',
+    backgroundColor: 'white',
+    paddingTop: '3%',
     flexDirection: 'column',
     flex: 1,
+    marginLeft: '7%',
+  },
+  swipeActions: {
+    flexDirection: 'row',
   },
   moreMarginWithThread: {
-    marginHorizontal: '7%',
+    marginLeft: '14%',
   },
   body: {
     marginLeft: 56,
   },
   comment: {
     marginBottom: '2%',
+    marginRight: '2%',
     top: -5,
   },
   date_time: {
@@ -153,35 +196,47 @@ const styles = StyleSheet.create({
     flexDirection: 'row',
     marginBottom: '3%',
   },
-
   flexer: {
     flex: 1,
   },
-
   repliesTextAndIconContainer: {
     flexDirection: 'row',
     alignItems: 'center',
   },
-
   repliesText: {
     color: TAGG_LIGHT_BLUE,
     fontWeight: '500',
     fontSize: normalize(12),
-    marginRight: '3%',
+    marginRight: '5%',
   },
   repliesBody: {
     width: SCREEN_WIDTH,
   },
-
   repliesDownArrow: {
     transform: [{rotate: '270deg'}],
     marginTop: '7%',
   },
-
   repliesUpArrow: {
     transform: [{rotate: '90deg'}],
     marginTop: '7%',
   },
+  actionText: {
+    color: 'white',
+    fontSize: normalize(12),
+    fontWeight: '500',
+    backgroundColor: 'transparent',
+    paddingHorizontal: '5%',
+    marginTop: '5%',
+  },
+  rightAction: {
+    alignItems: 'center',
+    flex: 1,
+    justifyContent: 'center',
+    flexDirection: 'column',
+  },
+  swipableContainer: {
+    backgroundColor: 'white',
+  },
 });
 
 export default CommentTile;
diff --git a/src/components/comments/CommentsContainer.tsx b/src/components/comments/CommentsContainer.tsx
index 0a19694b..fd4b32af 100644
--- a/src/components/comments/CommentsContainer.tsx
+++ b/src/components/comments/CommentsContainer.tsx
@@ -1,9 +1,10 @@
-import React, {useRef, useEffect, useState} from 'react';
+import React, {useEffect, useRef, useState} from 'react';
 import {StyleSheet} from 'react-native';
 import {ScrollView} from 'react-native-gesture-handler';
-import {useDispatch} from 'react-redux';
+import {useDispatch, useSelector} from 'react-redux';
 import {CommentTile} from '.';
 import {getComments} from '../../services';
+import {RootState} from '../../store/rootReducer';
 import {CommentType, ScreenType, TypeOfComment} from '../../types';
 export type CommentsContainerProps = {
   screenType: ScreenType;
@@ -32,6 +33,9 @@ const CommentsContainer: React.FC<CommentsContainerProps> = ({
   setCommentObjectInFocus,
   commentObjectInFocus,
 }) => {
+  const {username: loggedInUsername} = useSelector(
+    (state: RootState) => state.user.user,
+  );
   const [commentsList, setCommentsList] = useState<CommentType[]>([]);
   const dispatch = useDispatch();
   const ref = useRef<ScrollView>(null);
@@ -79,6 +83,8 @@ const CommentsContainer: React.FC<CommentsContainerProps> = ({
             screenType={screenType}
             typeOfComment={typeOfComment}
             setCommentObjectInFocus={setCommentObjectInFocus}
+            setNewCommentsAvailable={setNewCommentsAvailable}
+            canDelete={comment.commenter.username === loggedInUsername}
           />
         ))}
     </ScrollView>
@@ -86,9 +92,7 @@ const CommentsContainer: React.FC<CommentsContainerProps> = ({
 };
 
 const styles = StyleSheet.create({
-  scrollView: {
-    paddingHorizontal: 20,
-  },
+  scrollView: {},
   scrollViewContent: {
     justifyContent: 'center',
   },
diff --git a/src/constants/strings.ts b/src/constants/strings.ts
index 77ded7be..d3c81622 100644
--- a/src/constants/strings.ts
+++ b/src/constants/strings.ts
@@ -1,4 +1,3 @@
-
 /* eslint-disable */
 // Below is the regex to convert this into a csv for the Google Sheet
 // export const (.*) = .*?(['|"|`])(.*)\2;
@@ -15,6 +14,7 @@ export const ERROR_DUP_OLD_PWD = 'You may not use a previously used password';
 export const ERROR_EMAIL_IN_USE = 'Email already in use, please try another one';
 export const ERROR_FAILED_LOGIN_INFO = 'Login failed, please try re-entering your login information';
 export const ERROR_FAILED_TO_COMMENT = 'Unable to post comment, refresh and try again!';
+export const ERROR_FAILED_TO_DELETE_COMMENT = 'Unable to delete comment, refresh and try again!';
 export const ERROR_INVALID_INVITATION_CODE = 'Invitation code invalid, try again or talk to the friend that sent it 😬';
 export const ERROR_INVALID_LOGIN = 'Invalid login, Please login again';
 export const ERROR_INVALID_PWD_CODE = 'Looks like you have entered the wrong code, please try again';
diff --git a/src/services/CommentService.ts b/src/services/CommentService.ts
index 3baf0305..a9a01d77 100644
--- a/src/services/CommentService.ts
+++ b/src/services/CommentService.ts
@@ -99,3 +99,21 @@ export const getCommentsCount = async (
   }
   return comments_count;
 };
+
+export const deleteComment = async (id: string, isThread: boolean) => {
+  try {
+    const token = await AsyncStorage.getItem('token');
+    const url = isThread ? COMMENT_THREAD_ENDPOINT : COMMENTS_ENDPOINT;
+    const response = await fetch(url + `${id}/`, {
+      method: 'DELETE',
+      headers: {
+        Authorization: 'Token ' + token,
+      },
+    });
+    return response.status === 200;
+  } catch (error) {
+    console.log('Failed to delete a comment');
+    console.log(error);
+    return false;
+  }
+};
-- 
cgit v1.2.3-70-g09d2


From 56612885167c07462363aab6b606c807f58eeba5 Mon Sep 17 00:00:00 2001
From: Ivan Chen <ivan@tagg.id>
Date: Wed, 27 Jan 2021 16:27:17 -0500
Subject: fixed not refreshing

---
 src/components/comments/CommentTile.tsx       | 19 ++++++++++++++++---
 src/components/comments/CommentsContainer.tsx |  1 +
 src/services/CommentService.ts                |  1 -
 3 files changed, 17 insertions(+), 4 deletions(-)

(limited to 'src/components/comments/CommentTile.tsx')

diff --git a/src/components/comments/CommentTile.tsx b/src/components/comments/CommentTile.tsx
index e12276a9..58d2be25 100644
--- a/src/components/comments/CommentTile.tsx
+++ b/src/components/comments/CommentTile.tsx
@@ -1,4 +1,4 @@
-import React, {Fragment, useRef, useState} from 'react';
+import React, {Fragment, useEffect, useRef, useState} from 'react';
 import {Text, View} from 'react-native-animatable';
 import {ProfilePreview} from '../profile';
 import {CommentType, ScreenType, TypeOfComment} from '../../types';
@@ -23,6 +23,7 @@ interface CommentTileProps {
   screenType: ScreenType;
   typeOfComment: TypeOfComment;
   setCommentObjectInFocus?: (comment: CommentType | undefined) => void;
+  newCommentsAvailable: boolean;
   setNewCommentsAvailable: (available: boolean) => void;
   canDelete: boolean;
 }
@@ -32,14 +33,25 @@ const CommentTile: React.FC<CommentTileProps> = ({
   screenType,
   typeOfComment,
   setCommentObjectInFocus,
+  newCommentsAvailable,
   setNewCommentsAvailable,
   canDelete,
 }) => {
   const timePosted = getTimePosted(comment_object.date_created);
   const [showReplies, setShowReplies] = useState<boolean>(false);
+  const [newThreadAvailable, setNewThreadAvailable] = useState(true);
   const swipeRef = useRef<Swipeable>(null);
   const isThread = typeOfComment === 'Thread';
 
+  /**
+   * Bubbling up, for handling a new comment in a thread.
+   */
+  useEffect(() => {
+    if (newCommentsAvailable) {
+      setNewThreadAvailable(true);
+    }
+  }, [newCommentsAvailable]);
+
   /**
    * Case : A COMMENT IS IN FOCUS && REPLY SECTION IS HIDDEN
    *     Bring the current comment to focus
@@ -52,6 +64,7 @@ const CommentTile: React.FC<CommentTileProps> = ({
       if (!showReplies) {
         setCommentObjectInFocus(comment_object);
       } else {
+        setNewThreadAvailable(true);
         setCommentObjectInFocus(undefined);
       }
     }
@@ -150,8 +163,8 @@ const CommentTile: React.FC<CommentTileProps> = ({
         <CommentsContainer
           objectId={comment_object.comment_id}
           screenType={screenType}
-          setNewCommentsAvailable={() => {}}
-          newCommentsAvailable={true}
+          setNewCommentsAvailable={setNewThreadAvailable}
+          newCommentsAvailable={newThreadAvailable}
           typeOfComment={'Thread'}
         />
       )}
diff --git a/src/components/comments/CommentsContainer.tsx b/src/components/comments/CommentsContainer.tsx
index fd4b32af..d8134caf 100644
--- a/src/components/comments/CommentsContainer.tsx
+++ b/src/components/comments/CommentsContainer.tsx
@@ -83,6 +83,7 @@ const CommentsContainer: React.FC<CommentsContainerProps> = ({
             screenType={screenType}
             typeOfComment={typeOfComment}
             setCommentObjectInFocus={setCommentObjectInFocus}
+            newCommentsAvailable={newCommentsAvailable}
             setNewCommentsAvailable={setNewCommentsAvailable}
             canDelete={comment.commenter.username === loggedInUsername}
           />
diff --git a/src/services/CommentService.ts b/src/services/CommentService.ts
index a9a01d77..2faaa8db 100644
--- a/src/services/CommentService.ts
+++ b/src/services/CommentService.ts
@@ -23,7 +23,6 @@ export const getComments = async (
     const status = response.status;
     if (status === 200) {
       comments = await response.json();
-      console.log(comments[0]);
     } else {
       console.log('Could not load comments');
     }
-- 
cgit v1.2.3-70-g09d2


From 01b31b3f54ed58093df8e3f98e95268c0ace5f8a Mon Sep 17 00:00:00 2001
From: Ivan Chen <ivan@tagg.id>
Date: Wed, 27 Jan 2021 17:03:38 -0500
Subject: fixed bug to update replies count

---
 src/components/comments/CommentTile.tsx | 1 +
 1 file changed, 1 insertion(+)

(limited to 'src/components/comments/CommentTile.tsx')

diff --git a/src/components/comments/CommentTile.tsx b/src/components/comments/CommentTile.tsx
index 58d2be25..c6dd9fc1 100644
--- a/src/components/comments/CommentTile.tsx
+++ b/src/components/comments/CommentTile.tsx
@@ -65,6 +65,7 @@ const CommentTile: React.FC<CommentTileProps> = ({
         setCommentObjectInFocus(comment_object);
       } else {
         setNewThreadAvailable(true);
+        setNewCommentsAvailable(true);
         setCommentObjectInFocus(undefined);
       }
     }
-- 
cgit v1.2.3-70-g09d2


From 614fbcd8b0180b328019e6952ee1fc0de4643eaa Mon Sep 17 00:00:00 2001
From: Ivan Chen <ivan@tagg.id>
Date: Wed, 27 Jan 2021 18:43:57 -0500
Subject: fixed thumbnail for comments

---
 src/components/comments/CommentTile.tsx | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

(limited to 'src/components/comments/CommentTile.tsx')

diff --git a/src/components/comments/CommentTile.tsx b/src/components/comments/CommentTile.tsx
index 39605f2c..1247e89a 100644
--- a/src/components/comments/CommentTile.tsx
+++ b/src/components/comments/CommentTile.tsx
@@ -67,10 +67,7 @@ const CommentTile: React.FC<CommentTileProps> = ({
         ]}>
         <ProfilePreview
           profilePreview={{
-            id: comment_object.commenter.id,
-            username: comment_object.commenter.username,
-            first_name: comment_object.commenter.first_name,
-            last_name: comment_object.commenter.last_name,
+            ...comment_object.commenter,
           }}
           previewType={'Comment'}
           screenType={screenType}
-- 
cgit v1.2.3-70-g09d2


From dc9556867dd44b706c43678d40802a335ff40658 Mon Sep 17 00:00:00 2001
From: Ivan Chen <ivan@tagg.id>
Date: Wed, 27 Jan 2021 18:44:40 -0500
Subject: even better code

---
 src/components/comments/CommentTile.tsx | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

(limited to 'src/components/comments/CommentTile.tsx')

diff --git a/src/components/comments/CommentTile.tsx b/src/components/comments/CommentTile.tsx
index 1247e89a..237c65fc 100644
--- a/src/components/comments/CommentTile.tsx
+++ b/src/components/comments/CommentTile.tsx
@@ -66,9 +66,7 @@ const CommentTile: React.FC<CommentTileProps> = ({
           typeOfComment === 'Thread' ? styles.moreMarginWithThread : {},
         ]}>
         <ProfilePreview
-          profilePreview={{
-            ...comment_object.commenter,
-          }}
+          profilePreview={comment_object.commenter}
           previewType={'Comment'}
           screenType={screenType}
         />
-- 
cgit v1.2.3-70-g09d2


From 0e86cd3c972e54cf700cca65bb2493e84056276c Mon Sep 17 00:00:00 2001
From: Ashm Walia <ashmwalia@outlook.com>
Date: Fri, 29 Jan 2021 10:55:14 -0800
Subject: kind of works

---
 src/components/comments/CommentTile.tsx       | 27 ++++++----
 src/components/comments/CommentsContainer.tsx | 75 ++++++++++++++++++---------
 src/components/notifications/Notification.tsx |  1 +
 src/routes/main/MainStackNavigator.tsx        |  1 +
 src/screens/main/NotificationsScreen.tsx      |  2 +-
 src/screens/profile/IndividualMoment.tsx      |  9 ++--
 src/screens/profile/MomentCommentsScreen.tsx  |  5 +-
 7 files changed, 77 insertions(+), 43 deletions(-)

(limited to 'src/components/comments/CommentTile.tsx')

diff --git a/src/components/comments/CommentTile.tsx b/src/components/comments/CommentTile.tsx
index b631a985..347954b5 100644
--- a/src/components/comments/CommentTile.tsx
+++ b/src/components/comments/CommentTile.tsx
@@ -6,7 +6,12 @@ import {Alert, Animated, StyleSheet} from 'react-native';
 import ClockIcon from '../../assets/icons/clock-icon-01.svg';
 import {TAGG_LIGHT_BLUE} from '../../constants';
 import {RectButton, TouchableOpacity} from 'react-native-gesture-handler';
-import {getTimePosted, normalize, SCREEN_WIDTH} from '../../utils';
+import {
+  getTimePosted,
+  normalize,
+  SCREEN_HEIGHT,
+  SCREEN_WIDTH,
+} from '../../utils';
 import Arrow from '../../assets/icons/back-arrow-colored.svg';
 import Trash from '../../assets/ionicons/trash-outline.svg';
 import CommentsContainer from './CommentsContainer';
@@ -155,14 +160,16 @@ const CommentTile: React.FC<CommentTileProps> = ({
       </View>
 
       {/*** Show replies if toggle state is true */}
-      {showReplies && (
-        <CommentsContainer
-          objectId={comment_object.comment_id}
-          screenType={screenType}
-          setNewCommentsAvailable={setNewThreadAvailable}
-          newCommentsAvailable={newThreadAvailable}
-          typeOfComment={'Thread'}
-        />
+      {showReplies && comment_object.replies_count > 0 && (
+        <View style={{height: SCREEN_HEIGHT / 2.4}}>
+          <CommentsContainer
+            objectId={comment_object.comment_id}
+            screenType={screenType}
+            setNewCommentsAvailable={setNewThreadAvailable}
+            newCommentsAvailable={newThreadAvailable}
+            typeOfComment={'Thread'}
+          />
+        </View>
       )}
     </Swipeable>
   );
@@ -173,9 +180,9 @@ const styles = StyleSheet.create({
     borderBottomWidth: 1,
     borderColor: 'lightgray',
     backgroundColor: 'white',
-    paddingTop: '3%',
     flexDirection: 'column',
     flex: 1,
+    paddingTop: '3%',
     marginLeft: '7%',
   },
   swipeActions: {
diff --git a/src/components/comments/CommentsContainer.tsx b/src/components/comments/CommentsContainer.tsx
index d8134caf..d2f11b96 100644
--- a/src/components/comments/CommentsContainer.tsx
+++ b/src/components/comments/CommentsContainer.tsx
@@ -1,16 +1,17 @@
 import React, {useEffect, useRef, useState} from 'react';
 import {StyleSheet} from 'react-native';
-import {ScrollView} from 'react-native-gesture-handler';
+import {FlatList} from 'react-native-gesture-handler';
 import {useDispatch, useSelector} from 'react-redux';
 import {CommentTile} from '.';
 import {getComments} from '../../services';
 import {RootState} from '../../store/rootReducer';
 import {CommentType, ScreenType, TypeOfComment} from '../../types';
+import {SCREEN_HEIGHT} from '../../utils';
 export type CommentsContainerProps = {
   screenType: ScreenType;
-
   //objectId can be either moment_id or comment_id
   objectId: string;
+  commentId?: string;
   setCommentsLength?: (count: number) => void;
   newCommentsAvailable: boolean;
   setNewCommentsAvailable: (value: boolean) => void;
@@ -32,18 +33,21 @@ const CommentsContainer: React.FC<CommentsContainerProps> = ({
   typeOfComment,
   setCommentObjectInFocus,
   commentObjectInFocus,
+  commentId,
 }) => {
   const {username: loggedInUsername} = useSelector(
     (state: RootState) => state.user.user,
   );
   const [commentsList, setCommentsList] = useState<CommentType[]>([]);
   const dispatch = useDispatch();
-  const ref = useRef<ScrollView>(null);
+  const ref = useRef<FlatList<CommentType>>(null);
+  const [initialIndex, setInitialIndex] = useState<number>(0);
 
   useEffect(() => {
     //Scroll only if a new comment and not a reply was posted
     const shouldScroll = () =>
-      typeOfComment === 'Comment' && !commentObjectInFocus;
+      (typeOfComment === 'Comment' && !commentObjectInFocus) ||
+      typeOfComment === 'Thread';
     const loadComments = async () => {
       const comments = await getComments(objectId, typeOfComment === 'Thread');
       setCommentsList(comments);
@@ -55,9 +59,15 @@ const CommentsContainer: React.FC<CommentsContainerProps> = ({
     if (newCommentsAvailable) {
       loadComments();
       if (shouldScroll()) {
-        setTimeout(() => {
-          ref.current?.scrollToEnd();
-        }, 500);
+        if (commentId) {
+          const index = commentsList.findIndex(
+            (item) => item.comment_id === commentId,
+          );
+          setInitialIndex(index);
+        } else {
+          setInitialIndex(commentsList.length - 1);
+          ref.current?.scrollToEnd({animated: true});
+        }
       }
     }
   }, [
@@ -68,27 +78,44 @@ const CommentsContainer: React.FC<CommentsContainerProps> = ({
     setCommentsLength,
     typeOfComment,
     commentObjectInFocus,
+    commentId,
+    commentsList,
   ]);
 
+  const ITEM_HEIGHT = SCREEN_HEIGHT / 7.5;
+
+  const renderComment = ({item}: {item: CommentType}) => (
+    <CommentTile
+      key={item.comment_id}
+      comment_object={item}
+      screenType={screenType}
+      typeOfComment={typeOfComment}
+      setCommentObjectInFocus={setCommentObjectInFocus}
+      newCommentsAvailable={newCommentsAvailable}
+      setNewCommentsAvailable={setNewCommentsAvailable}
+      canDelete={item.commenter.username === loggedInUsername}
+    />
+  );
+
   return (
-    <ScrollView
+    <FlatList
+      data={commentsList}
       ref={ref}
-      style={styles.scrollView}
-      contentContainerStyle={styles.scrollViewContent}>
-      {commentsList &&
-        commentsList.map((comment: CommentType) => (
-          <CommentTile
-            key={comment.comment_id}
-            comment_object={comment}
-            screenType={screenType}
-            typeOfComment={typeOfComment}
-            setCommentObjectInFocus={setCommentObjectInFocus}
-            newCommentsAvailable={newCommentsAvailable}
-            setNewCommentsAvailable={setNewCommentsAvailable}
-            canDelete={comment.commenter.username === loggedInUsername}
-          />
-        ))}
-    </ScrollView>
+      keyExtractor={(item, index) => index.toString()}
+      decelerationRate={'fast'}
+      snapToAlignment={'start'}
+      snapToInterval={ITEM_HEIGHT}
+      renderItem={renderComment}
+      showsVerticalScrollIndicator={false}
+      initialScrollIndex={initialIndex}
+      contentContainerStyle={styles.scrollViewContent}
+      getItemLayout={(data, index) => ({
+        length: ITEM_HEIGHT,
+        offset: ITEM_HEIGHT * index,
+        index,
+      })}
+      pagingEnabled
+    />
   );
 };
 
diff --git a/src/components/notifications/Notification.tsx b/src/components/notifications/Notification.tsx
index 94367304..c754f941 100644
--- a/src/components/notifications/Notification.tsx
+++ b/src/components/notifications/Notification.tsx
@@ -122,6 +122,7 @@ const Notification: React.FC<NotificationProps> = (props) => {
             navigation.push('MomentCommentsScreen', {
               moment_id: moment.moment_id,
               screenType,
+              comment_id: notification_object?.comment_id,
             });
           }, 500);
         }
diff --git a/src/routes/main/MainStackNavigator.tsx b/src/routes/main/MainStackNavigator.tsx
index bd838ef2..663aeaea 100644
--- a/src/routes/main/MainStackNavigator.tsx
+++ b/src/routes/main/MainStackNavigator.tsx
@@ -37,6 +37,7 @@ export type MainStackParams = {
     moment_id: string;
     userXId: string | undefined;
     screenType: ScreenType;
+    comment_id?: string;
   };
   FriendsListScreen: {
     userXId: string | undefined;
diff --git a/src/screens/main/NotificationsScreen.tsx b/src/screens/main/NotificationsScreen.tsx
index 4bdee942..d9952aa8 100644
--- a/src/screens/main/NotificationsScreen.tsx
+++ b/src/screens/main/NotificationsScreen.tsx
@@ -70,7 +70,7 @@ const NotificationsScreen: React.FC = () => {
 
       //Called when user leaves the screen
       return () => resetNewNotificationFlag();
-    }, [newNotificationReceived]),
+    }, [newNotificationReceived, dispatch, refreshNotifications]),
   );
 
   // handles storing and fetching the "previously viewed" information
diff --git a/src/screens/profile/IndividualMoment.tsx b/src/screens/profile/IndividualMoment.tsx
index ea0c8fb6..8c1dc327 100644
--- a/src/screens/profile/IndividualMoment.tsx
+++ b/src/screens/profile/IndividualMoment.tsx
@@ -4,12 +4,12 @@ import {StackNavigationProp} from '@react-navigation/stack';
 import React from 'react';
 import {FlatList, StyleSheet, View} from 'react-native';
 import {useSelector} from 'react-redux';
-import {ProfileStackParams} from 'src/routes/main/ProfileStack';
 import {
   IndividualMomentTitleBar,
   MomentPostContent,
   MomentPostHeader,
 } from '../../components';
+import {MainStackParams} from '../../routes';
 import {RootState} from '../../store/rootreducer';
 import {MomentType} from '../../types';
 import {SCREEN_HEIGHT, SCREEN_WIDTH, StatusBarHeight} from '../../utils';
@@ -17,12 +17,9 @@ import {SCREEN_HEIGHT, SCREEN_WIDTH, StatusBarHeight} from '../../utils';
 /**
  * Individual moment view opened when user clicks on a moment tile
  */
-type IndividualMomentRouteProp = RouteProp<
-  ProfileStackParams,
-  'IndividualMoment'
->;
+type IndividualMomentRouteProp = RouteProp<MainStackParams, 'IndividualMoment'>;
 type IndividualMomentNavigationProp = StackNavigationProp<
-  ProfileStackParams,
+  MainStackParams,
   'IndividualMoment'
 >;
 interface IndividualMomentProps {
diff --git a/src/screens/profile/MomentCommentsScreen.tsx b/src/screens/profile/MomentCommentsScreen.tsx
index 58422f0f..5c3b8579 100644
--- a/src/screens/profile/MomentCommentsScreen.tsx
+++ b/src/screens/profile/MomentCommentsScreen.tsx
@@ -28,7 +28,7 @@ interface MomentCommentsScreenProps {
 
 const MomentCommentsScreen: React.FC<MomentCommentsScreenProps> = ({route}) => {
   const navigation = useNavigation();
-  const {moment_id, screenType} = route.params;
+  const {moment_id, screenType, comment_id} = route.params;
 
   //Receives comment length from child CommentsContainer
   const [commentsLength, setCommentsLength] = useState<number>(0);
@@ -55,6 +55,7 @@ const MomentCommentsScreen: React.FC<MomentCommentsScreenProps> = ({route}) => {
         <View style={styles.body}>
           <CommentsContainer
             objectId={moment_id}
+            commentId={comment_id}
             screenType={screenType}
             setCommentsLength={setCommentsLength}
             newCommentsAvailable={newCommentsAvailable}
@@ -107,7 +108,7 @@ const styles = StyleSheet.create({
     fontWeight: '400',
   },
   body: {
-    width: SCREEN_WIDTH,
+    width: SCREEN_WIDTH * 0.9,
     height: SCREEN_HEIGHT * 0.8,
     paddingTop: '3%',
   },
-- 
cgit v1.2.3-70-g09d2


From 830297c6f7ce554946246540a7239ab5b3ed712a Mon Sep 17 00:00:00 2001
From: Ashm Walia <ashmwalia@outlook.com>
Date: Fri, 29 Jan 2021 12:09:54 -0800
Subject: Fix

---
 src/components/comments/CommentTile.tsx | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

(limited to 'src/components/comments/CommentTile.tsx')

diff --git a/src/components/comments/CommentTile.tsx b/src/components/comments/CommentTile.tsx
index 347954b5..a1ee582b 100644
--- a/src/components/comments/CommentTile.tsx
+++ b/src/components/comments/CommentTile.tsx
@@ -18,6 +18,7 @@ import CommentsContainer from './CommentsContainer';
 import Swipeable from 'react-native-gesture-handler/Swipeable';
 import {deleteComment} from '../../services';
 import {ERROR_FAILED_TO_DELETE_COMMENT} from '../../constants/strings';
+import {min} from 'moment';
 
 /**
  * Displays users's profile picture, comment posted by them and the time difference between now and when a comment was posted.
@@ -161,7 +162,13 @@ const CommentTile: React.FC<CommentTileProps> = ({
 
       {/*** Show replies if toggle state is true */}
       {showReplies && comment_object.replies_count > 0 && (
-        <View style={{height: SCREEN_HEIGHT / 2.4}}>
+        <View
+          style={{
+            height: Math.min(
+              SCREEN_HEIGHT / 2.4,
+              (SCREEN_HEIGHT / 8) * comment_object.replies_count,
+            ),
+          }}>
           <CommentsContainer
             objectId={comment_object.comment_id}
             screenType={screenType}
-- 
cgit v1.2.3-70-g09d2


From cf77496e68b9ef97c833da35fcef2a29bd1f9ae5 Mon Sep 17 00:00:00 2001
From: Ashm Walia <ashmwalia@outlook.com>
Date: Fri, 29 Jan 2021 13:57:08 -0800
Subject: Done

---
 src/components/comments/CommentTile.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'src/components/comments/CommentTile.tsx')

diff --git a/src/components/comments/CommentTile.tsx b/src/components/comments/CommentTile.tsx
index a1ee582b..e775a609 100644
--- a/src/components/comments/CommentTile.tsx
+++ b/src/components/comments/CommentTile.tsx
@@ -166,7 +166,7 @@ const CommentTile: React.FC<CommentTileProps> = ({
           style={{
             height: Math.min(
               SCREEN_HEIGHT / 2.4,
-              (SCREEN_HEIGHT / 8) * comment_object.replies_count,
+              (SCREEN_HEIGHT / 7.5) * comment_object.replies_count,
             ),
           }}>
           <CommentsContainer
-- 
cgit v1.2.3-70-g09d2


From a3000926cb26d9ca2afba116d875653783fb622b Mon Sep 17 00:00:00 2001
From: Ashm Walia <ashmwalia@outlook.com>
Date: Sun, 31 Jan 2021 02:25:53 -0800
Subject: Fixed

---
 src/components/comments/AddComment.tsx        |  16 +++-
 src/components/comments/CommentTile.tsx       | 114 +++++++++++++++-----------
 src/components/comments/CommentsContainer.tsx |  97 +++++++++++++++-------
 src/components/notifications/Notification.tsx |  80 +++++++++++++-----
 src/store/actions/user.ts                     |  18 ++++
 src/store/initialStates.ts                    |   2 +
 src/store/reducers/userReducer.ts             |   6 ++
 src/types/types.ts                            |  13 ++-
 8 files changed, 243 insertions(+), 103 deletions(-)

(limited to 'src/components/comments/CommentTile.tsx')

diff --git a/src/components/comments/AddComment.tsx b/src/components/comments/AddComment.tsx
index 44f49748..56011f05 100644
--- a/src/components/comments/AddComment.tsx
+++ b/src/components/comments/AddComment.tsx
@@ -8,10 +8,11 @@ import {
   View,
 } from 'react-native';
 import {TextInput, TouchableOpacity} from 'react-native-gesture-handler';
-import {useSelector} from 'react-redux';
+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 {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils';
 
@@ -38,6 +39,7 @@ const AddComment: React.FC<AddCommentProps> = ({
   const [keyboardVisible, setKeyboardVisible] = React.useState(false);
 
   const {avatar} = useSelector((state: RootState) => state.user);
+  const dispatch = useDispatch();
 
   const addComment = async () => {
     const trimmed = comment.trim();
@@ -52,6 +54,18 @@ const AddComment: React.FC<AddCommentProps> = ({
 
     if (postedComment) {
       setComment('');
+
+      //Set new reply posted object
+      //This helps us show the latest reply on top
+      //Data set is kind of stale but it works
+      if (isCommentInFocus) {
+        dispatch(
+          updateReplyPosted({
+            comment_id: postedComment.comment_id,
+            parent_comment: {comment_id: objectId},
+          }),
+        );
+      }
       setNewCommentsAvailable(true);
     }
   };
diff --git a/src/components/comments/CommentTile.tsx b/src/components/comments/CommentTile.tsx
index e775a609..be113523 100644
--- a/src/components/comments/CommentTile.tsx
+++ b/src/components/comments/CommentTile.tsx
@@ -1,3 +1,4 @@
+/* eslint-disable radix */
 import React, {Fragment, useEffect, useRef, useState} from 'react';
 import {Text, View} from 'react-native-animatable';
 import {ProfilePreview} from '../profile';
@@ -6,19 +7,15 @@ import {Alert, Animated, StyleSheet} from 'react-native';
 import ClockIcon from '../../assets/icons/clock-icon-01.svg';
 import {TAGG_LIGHT_BLUE} from '../../constants';
 import {RectButton, TouchableOpacity} from 'react-native-gesture-handler';
-import {
-  getTimePosted,
-  normalize,
-  SCREEN_HEIGHT,
-  SCREEN_WIDTH,
-} from '../../utils';
+import {getTimePosted, normalize, SCREEN_WIDTH} from '../../utils';
 import Arrow from '../../assets/icons/back-arrow-colored.svg';
 import Trash from '../../assets/ionicons/trash-outline.svg';
 import CommentsContainer from './CommentsContainer';
 import Swipeable from 'react-native-gesture-handler/Swipeable';
-import {deleteComment} from '../../services';
+import {deleteComment, getCommentsCount} from '../../services';
 import {ERROR_FAILED_TO_DELETE_COMMENT} from '../../constants/strings';
-import {min} from 'moment';
+import {useSelector} from 'react-redux';
+import {RootState} from '../../store/rootReducer';
 
 /**
  * Displays users's profile picture, comment posted by them and the time difference between now and when a comment was posted.
@@ -45,10 +42,13 @@ const CommentTile: React.FC<CommentTileProps> = ({
 }) => {
   const timePosted = getTimePosted(comment_object.date_created);
   const [showReplies, setShowReplies] = useState<boolean>(false);
+  const [showKeyboard, setShowKeyboard] = useState<boolean>(false);
   const [newThreadAvailable, setNewThreadAvailable] = useState(true);
   const swipeRef = useRef<Swipeable>(null);
   const isThread = typeOfComment === 'Thread';
 
+  const {replyPosted} = useSelector((state: RootState) => state.user);
+
   /**
    * Bubbling up, for handling a new comment in a thread.
    */
@@ -58,23 +58,43 @@ const CommentTile: React.FC<CommentTileProps> = ({
     }
   }, [newCommentsAvailable]);
 
+  useEffect(() => {
+    if (replyPosted && typeOfComment === 'Comment') {
+      if (replyPosted.parent_comment.comment_id === comment_object.comment_id) {
+        setShowReplies(true);
+      }
+    }
+    // eslint-disable-next-line react-hooks/exhaustive-deps
+  }, [replyPosted]);
+
   /**
    * Case : A COMMENT IS IN FOCUS && REPLY SECTION IS HIDDEN
    *     Bring the current comment to focus
    * Case : No COMMENT IS IN FOCUS && REPLY SECTION IS SHOWN
    *     Unfocus comment in focus
-   * In any case toggle value of showReplies
    */
-  const toggleReplies = () => {
-    if (setCommentObjectInFocus) {
-      if (!showReplies) {
-        setCommentObjectInFocus(comment_object);
-      } else {
-        setNewThreadAvailable(true);
-        setNewCommentsAvailable(true);
-        setCommentObjectInFocus(undefined);
+  const toggleAddComment = () => {
+    //Do not allow user to reply to a thread
+    if (!isThread) {
+      if (setCommentObjectInFocus) {
+        if (!showKeyboard) {
+          setCommentObjectInFocus(comment_object);
+        } else {
+          setCommentObjectInFocus(undefined);
+        }
       }
+      setShowKeyboard(!showKeyboard);
     }
+  };
+
+  const toggleReplies = async () => {
+    if (showReplies) {
+      //To update count of replies in case we deleted a reply
+      comment_object.replies_count = parseInt(
+        await getCommentsCount(comment_object.comment_id, true),
+      );
+    }
+    setNewThreadAvailable(true);
     setShowReplies(!showReplies);
   };
 
@@ -110,7 +130,7 @@ const CommentTile: React.FC<CommentTileProps> = ({
     );
   };
 
-  const renderRightActions = (progress) =>
+  const renderRightActions = (progress: Animated.AnimatedInterpolation) =>
     canDelete ? (
       <View style={styles.swipeActions}>
         {renderRightAction('Delete', '#c42634', progress)}
@@ -133,48 +153,42 @@ const CommentTile: React.FC<CommentTileProps> = ({
           previewType={'Comment'}
           screenType={screenType}
         />
-        <TouchableOpacity style={styles.body} onPress={toggleReplies}>
+        <TouchableOpacity style={styles.body} onPress={toggleAddComment}>
           <Text style={styles.comment}>{comment_object.comment}</Text>
           <View style={styles.clockIconAndTime}>
             <ClockIcon style={styles.clockIcon} />
             <Text style={styles.date_time}>{' ' + timePosted}</Text>
             <View style={styles.flexer} />
-
-            {/*** Show replies text only if there are some replies present */}
-            {typeOfComment === 'Comment' && comment_object.replies_count > 0 && (
-              <View style={styles.repliesTextAndIconContainer}>
-                <Text style={styles.repliesText}>{getRepliesText()}</Text>
-                <Arrow
-                  width={12}
-                  height={11}
-                  color={TAGG_LIGHT_BLUE}
-                  style={
-                    !showReplies
-                      ? styles.repliesDownArrow
-                      : styles.repliesUpArrow
-                  }
-                />
-              </View>
-            )}
           </View>
         </TouchableOpacity>
+        {/*** Show replies text only if there are some replies present */}
+        {typeOfComment === 'Comment' && comment_object.replies_count > 0 && (
+          <TouchableOpacity
+            style={styles.repliesTextAndIconContainer}
+            onPress={toggleReplies}>
+            <Text style={styles.repliesText}>{getRepliesText()}</Text>
+            <Arrow
+              width={12}
+              height={11}
+              color={TAGG_LIGHT_BLUE}
+              style={
+                !showReplies ? styles.repliesDownArrow : styles.repliesUpArrow
+              }
+            />
+          </TouchableOpacity>
+        )}
       </View>
 
       {/*** Show replies if toggle state is true */}
-      {showReplies && comment_object.replies_count > 0 && (
-        <View
-          style={{
-            height: Math.min(
-              SCREEN_HEIGHT / 2.4,
-              (SCREEN_HEIGHT / 7.5) * comment_object.replies_count,
-            ),
-          }}>
+      {showReplies && (
+        <View>
           <CommentsContainer
             objectId={comment_object.comment_id}
             screenType={screenType}
             setNewCommentsAvailable={setNewThreadAvailable}
             newCommentsAvailable={newThreadAvailable}
             typeOfComment={'Thread'}
+            commentId={replyPosted?.comment_id}
           />
         </View>
       )}
@@ -190,6 +204,7 @@ const styles = StyleSheet.create({
     flexDirection: 'column',
     flex: 1,
     paddingTop: '3%',
+    paddingBottom: '5%',
     marginLeft: '7%',
   },
   swipeActions: {
@@ -204,7 +219,6 @@ const styles = StyleSheet.create({
   comment: {
     marginBottom: '2%',
     marginRight: '2%',
-    top: -5,
   },
   date_time: {
     color: 'gray',
@@ -217,7 +231,7 @@ const styles = StyleSheet.create({
   },
   clockIconAndTime: {
     flexDirection: 'row',
-    marginBottom: '3%',
+    marginTop: '3%',
   },
   flexer: {
     flex: 1,
@@ -225,23 +239,25 @@ const styles = StyleSheet.create({
   repliesTextAndIconContainer: {
     flexDirection: 'row',
     alignItems: 'center',
+    marginTop: '5%',
+    marginLeft: 56,
   },
   repliesText: {
     color: TAGG_LIGHT_BLUE,
     fontWeight: '500',
     fontSize: normalize(12),
-    marginRight: '5%',
+    marginRight: '1%',
   },
   repliesBody: {
     width: SCREEN_WIDTH,
   },
   repliesDownArrow: {
     transform: [{rotate: '270deg'}],
-    marginTop: '7%',
+    marginTop: '1%',
   },
   repliesUpArrow: {
     transform: [{rotate: '90deg'}],
-    marginTop: '7%',
+    marginTop: '1%',
   },
   actionText: {
     color: 'white',
diff --git a/src/components/comments/CommentsContainer.tsx b/src/components/comments/CommentsContainer.tsx
index a0e94828..c72da2b7 100644
--- a/src/components/comments/CommentsContainer.tsx
+++ b/src/components/comments/CommentsContainer.tsx
@@ -4,6 +4,7 @@ import {FlatList} from 'react-native-gesture-handler';
 import {useDispatch, useSelector} from 'react-redux';
 import {CommentTile} from '.';
 import {getComments} from '../../services';
+import {updateReplyPosted} from '../../store/actions';
 import {RootState} from '../../store/rootReducer';
 import {CommentType, ScreenType, TypeOfComment} from '../../types';
 import {SCREEN_HEIGHT} from '../../utils';
@@ -41,36 +42,28 @@ const CommentsContainer: React.FC<CommentsContainerProps> = ({
   const [commentsList, setCommentsList] = useState<CommentType[]>([]);
   const dispatch = useDispatch();
   const ref = useRef<FlatList<CommentType>>(null);
-  const [initialIndex, setInitialIndex] = useState<number>(0);
 
   useEffect(() => {
-    //Scroll only if a new comment and not a reply was posted
-    const shouldScroll = () =>
-      (typeOfComment === 'Comment' && !commentObjectInFocus) ||
-      typeOfComment === 'Thread';
     const loadComments = async () => {
-      const comments = await getComments(objectId, typeOfComment === 'Thread');
-      setCommentsList(comments);
-      if (setCommentsLength) {
-        setCommentsLength(comments.length);
-      }
-      setNewCommentsAvailable(false);
+      await getComments(objectId, typeOfComment === 'Thread').then(
+        (comments) => {
+          if (comments && subscribedToLoadComments) {
+            setCommentsList(comments);
+            if (setCommentsLength) {
+              setCommentsLength(comments.length);
+            }
+            setNewCommentsAvailable(false);
+          }
+        },
+      );
     };
+    let subscribedToLoadComments = true;
     if (newCommentsAvailable) {
       loadComments();
-      if (shouldScroll()) {
-        if (commentId) {
-          const index = commentsList.findIndex(
-            (item) => item.comment_id === commentId,
-          );
-          setInitialIndex(index);
-        } else {
-          setTimeout(() => {
-            ref.current?.scrollToEnd({animated: true});
-          }, 500);
-        }
-      }
     }
+    return () => {
+      subscribedToLoadComments = false;
+    };
   }, [
     dispatch,
     objectId,
@@ -78,12 +71,61 @@ const CommentsContainer: React.FC<CommentsContainerProps> = ({
     setNewCommentsAvailable,
     setCommentsLength,
     typeOfComment,
-    commentObjectInFocus,
-    commentId,
-    commentsList,
   ]);
 
-  const ITEM_HEIGHT = SCREEN_HEIGHT / 7.5;
+  // eslint-disable-next-line no-shadow
+  const swapCommentTo = (commentId: string, toIndex: number) => {
+    const index = commentsList.findIndex(
+      (item) => item.comment_id === commentId,
+    );
+    if (index > 0) {
+      let comments = [...commentsList];
+      const temp = comments[index];
+      comments[index] = comments[toIndex];
+      comments[toIndex] = temp;
+      setCommentsList(comments);
+    }
+  };
+
+  useEffect(() => {
+    //Scroll only if a new comment and not a reply was posted
+    const shouldScroll = () =>
+      typeOfComment === 'Comment' && !commentObjectInFocus;
+
+    const performAction = () => {
+      if (commentId) {
+        swapCommentTo(commentId, 0);
+      } else if (shouldScroll()) {
+        setTimeout(() => {
+          ref.current?.scrollToEnd({animated: true});
+        }, 500);
+      }
+    };
+    if (commentsList) {
+      //Bring the relevant comment to top if a comment id is present else scroll if necessary
+      performAction();
+    }
+
+    //Clean up the reply id present in store
+    return () => {
+      if (commentId && typeOfComment === 'Thread') {
+        setTimeout(() => {
+          dispatch(updateReplyPosted(undefined));
+        }, 200);
+      }
+    };
+    // eslint-disable-next-line react-hooks/exhaustive-deps
+  }, [commentsList, commentId]);
+
+  //WIP : TODO : Bring the comment in focus above the keyboard
+  // useEffect(() => {
+  //   if (commentObjectInFocus && commentsList.length >= 3) {
+  //     swapCommentTo(commentObjectInFocus.comment_id, 2);
+  //   }
+  //   // eslint-disable-next-line react-hooks/exhaustive-deps
+  // }, [commentObjectInFocus]);
+
+  const ITEM_HEIGHT = SCREEN_HEIGHT / 7.0;
 
   const renderComment = ({item}: {item: CommentType}) => (
     <CommentTile
@@ -108,7 +150,6 @@ const CommentsContainer: React.FC<CommentsContainerProps> = ({
       snapToInterval={ITEM_HEIGHT}
       renderItem={renderComment}
       showsVerticalScrollIndicator={false}
-      initialScrollIndex={initialIndex}
       contentContainerStyle={styles.scrollViewContent}
       getItemLayout={(data, index) => ({
         length: ITEM_HEIGHT,
diff --git a/src/components/notifications/Notification.tsx b/src/components/notifications/Notification.tsx
index c754f941..e40153ea 100644
--- a/src/components/notifications/Notification.tsx
+++ b/src/components/notifications/Notification.tsx
@@ -1,18 +1,29 @@
 import {useNavigation} from '@react-navigation/native';
 import React, {useEffect, useState} from 'react';
-import {Image, StyleSheet, Text, View} from 'react-native';
+import {Alert, Image, StyleSheet, Text, View} from 'react-native';
 import {TouchableWithoutFeedback} from 'react-native-gesture-handler';
 import {useDispatch, useStore} from 'react-redux';
-import {loadImageFromURL, loadMomentThumbnail} from '../../services';
+import {
+  loadImageFromURL,
+  loadMoments,
+  loadMomentThumbnail,
+} from '../../services';
 import {
   acceptFriendRequest,
   declineFriendRequest,
   loadUserNotifications,
+  updateReplyPosted,
   updateUserXFriends,
 } from '../../store/actions';
 import {RootState} from '../../store/rootReducer';
 import {MomentType, NotificationType, ScreenType} from '../../types';
-import {fetchUserX, SCREEN_HEIGHT, userXInStore} from '../../utils';
+import {
+  fetchUserX,
+  getTokenOrLogout,
+  handleOpenSocialUrlOnBrowser,
+  SCREEN_HEIGHT,
+  userXInStore,
+} from '../../utils';
 import AcceptDeclineButtons from '../common/AcceptDeclineButtons';
 
 interface NotificationProps {
@@ -60,7 +71,11 @@ const Notification: React.FC<NotificationProps> = (props) => {
       }
     };
     if (notification_type === 'CMT' && notification_object) {
-      loadMomentImage(notification_object.moment_id);
+      loadMomentImage(
+        notification_object.moment_id
+          ? notification_object.moment_id
+          : notification_object.parent_comment.moment_id,
+      );
       return () => {
         mounted = false;
       };
@@ -84,35 +99,56 @@ const Notification: React.FC<NotificationProps> = (props) => {
         });
         break;
       case 'CMT':
-        // find the moment we need to display
+        //Notification object is set to null if the comment / comment_thread / moment gets deleted
+        if (!notification_object) {
+          Alert.alert('The comment / moment was probably deleted by the user');
+          break;
+        }
+        let {moment_id} = notification_object;
+        let {comment_id} = notification_object;
+
+        //If this is a thread, get comment_id and moment_id from parent_comment
+        if (!notification_object?.moment_id) {
+          moment_id = notification_object?.parent_comment?.moment_id;
+          comment_id = notification_object?.parent_comment?.comment_id;
+        }
+
+        console.log('Problem');
+
+        // Now find the moment we need to display
         let moment: MomentType | undefined = loggedInUserMoments?.find(
-          (m) => m.moment_id === notification_object?.moment_id,
+          (m) => m.moment_id === moment_id,
         );
         let userXId;
 
-        //This needs to be done if user replies to a comment on a moment that is not user's own moment
+        // If moment does not belong to the logged in user, then the comment was probably a reply to logged in user's comment
+        // on userX's moment
+        // Load moments for userX
         if (!moment) {
+          let moments: MomentType[] = [];
           try {
             if (!userXInStore(state, screenType, id)) {
-              await fetchUserX(
-                dispatch,
-                {userId: id, username: username},
-                screenType,
-              );
+              console.log('Problem');
+              const token = await getTokenOrLogout(dispatch);
+              moments = await loadMoments(id, token);
+            } else {
+              moments = state.userX[screenType][id].moments;
             }
-
-            //Wait for data to be loaded
-            setTimeout(() => {}, 200);
-            const {moments} = state.userX[screenType][id];
-            moment = moments?.find(
-              (m) => m.moment_id === notification_object?.moment_id,
-            );
-            userXId = id;
           } catch (err) {
             console.log(err);
           }
+
+          setTimeout(() => {}, 700);
+          moment = moments?.find((m) => m.moment_id === moment_id);
+          userXId = id;
         }
+
+        console.log(moment);
+        //Now if moment was found, navigate to the respective moment
         if (moment) {
+          if (notification_object?.parent_comment) {
+            dispatch(updateReplyPosted(notification_object));
+          }
           navigation.push('IndividualMoment', {
             moment,
             userXId: userXId, // we're only viewing our own moment here
@@ -120,9 +156,9 @@ const Notification: React.FC<NotificationProps> = (props) => {
           });
           setTimeout(() => {
             navigation.push('MomentCommentsScreen', {
-              moment_id: moment.moment_id,
+              moment_id: moment_id,
               screenType,
-              comment_id: notification_object?.comment_id,
+              comment_id: comment_id,
             });
           }, 500);
         }
diff --git a/src/store/actions/user.ts b/src/store/actions/user.ts
index 0b1ea789..af942592 100644
--- a/src/store/actions/user.ts
+++ b/src/store/actions/user.ts
@@ -1,3 +1,4 @@
+import { CommentThreadType } from './../../types/types';
 import {RootState} from '../rootReducer';
 import {UserType} from '../../types/types';
 import {loadProfileInfo, loadAvatar, loadCover} from '../../services';
@@ -9,6 +10,7 @@ import {
   profileCompletionStageUpdated,
   setIsOnboardedUser,
   setNewNotificationReceived,
+  setReplyPosted,
 } from '../reducers';
 import {getTokenOrLogout} from '../../utils';
 
@@ -111,6 +113,22 @@ export const updateNewNotificationReceived = (
   }
 };
 
+export const updateReplyPosted = (
+  replyPosted: CommentThreadType | undefined,
+): ThunkAction<Promise<void>, RootState, unknown, Action<string>> => async (
+  dispatch,
+) => {
+  console.log(replyPosted);
+  try {
+    dispatch({
+      type: setReplyPosted.type,
+      payload: {replyPosted},
+    });
+  } catch (error) {
+    console.log(error);
+  }
+};
+
 export const logout = (): ThunkAction<
   Promise<void>,
   RootState,
diff --git a/src/store/initialStates.ts b/src/store/initialStates.ts
index 2a5b76db..8d137a5d 100644
--- a/src/store/initialStates.ts
+++ b/src/store/initialStates.ts
@@ -1,3 +1,4 @@
+import {CommentThreadType} from './../types/types';
 import {
   ExploreSectionType,
   MomentType,
@@ -44,6 +45,7 @@ export const NO_USER_DATA = {
   cover: <string | null>'',
   isOnboardedUser: false,
   newNotificationReceived: false,
+  replyPosted: <CommentThreadType | undefined>undefined,
 };
 
 export const NO_FRIENDS_DATA = {
diff --git a/src/store/reducers/userReducer.ts b/src/store/reducers/userReducer.ts
index ce497677..0ef739ac 100644
--- a/src/store/reducers/userReducer.ts
+++ b/src/store/reducers/userReducer.ts
@@ -53,6 +53,11 @@ const userDataSlice = createSlice({
     setNewNotificationReceived: (state, action) => {
       state.newNotificationReceived = action.payload.newNotificationReceived;
     },
+
+    setReplyPosted: (state, action) => {
+      console.log(action.payload.replyPosted);
+      state.replyPosted = action.payload.replyPosted;
+    },
   },
 });
 
@@ -63,5 +68,6 @@ export const {
   profileCompletionStageUpdated,
   setIsOnboardedUser,
   setNewNotificationReceived,
+  setReplyPosted,
 } = userDataSlice.actions;
 export const userDataReducer = userDataSlice.reducer;
diff --git a/src/types/types.ts b/src/types/types.ts
index 1d800423..1775cd5f 100644
--- a/src/types/types.ts
+++ b/src/types/types.ts
@@ -88,13 +88,20 @@ export interface MomentType {
   thumbnail_url: string;
 }
 
-export interface CommentType {
+export interface CommentBaseType {
   comment_id: string;
   comment: string;
   date_created: string;
+  commenter: ProfilePreviewType;
+}
+
+export interface CommentType extends CommentBaseType {
   moment_id: string;
   replies_count: number;
-  commenter: ProfilePreviewType;
+}
+
+export interface CommentThreadType extends CommentBaseType {
+  parent_comment: CommentType;
 }
 
 export type PreviewType =
@@ -173,7 +180,7 @@ export type NotificationType = {
   actor: ProfilePreviewType;
   verbage: string;
   notification_type: 'DFT' | 'FRD_REQ' | 'FRD_ACPT' | 'FRD_DEC' | 'CMT';
-  notification_object: CommentType | undefined;
+  notification_object: CommentType | CommentThreadType | undefined;
   timestamp: string;
   unread: boolean;
 };
-- 
cgit v1.2.3-70-g09d2

