aboutsummaryrefslogtreecommitdiff
path: root/src/components/comments/CommentsContainer.tsx
diff options
context:
space:
mode:
authorIvan Chen <ivan@tagg.id>2021-02-01 16:01:03 -0500
committerIvan Chen <ivan@tagg.id>2021-02-01 16:01:03 -0500
commit8d1013e86cf2d66671c337d49a80da157802ad86 (patch)
tree656b1656068bb6636919359d4faaf7051994ff74 /src/components/comments/CommentsContainer.tsx
parent951d85348acef13ec7830629205c30ad5f766bee (diff)
parent7a09cc96bf1fe468a612bb44362bbef24fccc773 (diff)
Merge branch 'master' into TMA-546-Onboarding-Page
Diffstat (limited to 'src/components/comments/CommentsContainer.tsx')
-rw-r--r--src/components/comments/CommentsContainer.tsx171
1 files changed, 171 insertions, 0 deletions
diff --git a/src/components/comments/CommentsContainer.tsx b/src/components/comments/CommentsContainer.tsx
new file mode 100644
index 00000000..c72da2b7
--- /dev/null
+++ b/src/components/comments/CommentsContainer.tsx
@@ -0,0 +1,171 @@
+import React, {useEffect, useRef, useState} from 'react';
+import {StyleSheet} from 'react-native';
+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';
+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;
+ 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,
+ commentId,
+}) => {
+ const {username: loggedInUsername} = useSelector(
+ (state: RootState) => state.user.user,
+ );
+ const [commentsList, setCommentsList] = useState<CommentType[]>([]);
+ const dispatch = useDispatch();
+ const ref = useRef<FlatList<CommentType>>(null);
+
+ useEffect(() => {
+ const loadComments = async () => {
+ 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();
+ }
+ return () => {
+ subscribedToLoadComments = false;
+ };
+ }, [
+ dispatch,
+ objectId,
+ newCommentsAvailable,
+ setNewCommentsAvailable,
+ setCommentsLength,
+ typeOfComment,
+ ]);
+
+ // 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
+ key={item.comment_id}
+ comment_object={item}
+ screenType={screenType}
+ typeOfComment={typeOfComment}
+ setCommentObjectInFocus={setCommentObjectInFocus}
+ newCommentsAvailable={newCommentsAvailable}
+ setNewCommentsAvailable={setNewCommentsAvailable}
+ canDelete={item.commenter.username === loggedInUsername}
+ />
+ );
+
+ return (
+ <FlatList
+ data={commentsList}
+ ref={ref}
+ keyExtractor={(item, index) => index.toString()}
+ decelerationRate={'fast'}
+ snapToAlignment={'start'}
+ snapToInterval={ITEM_HEIGHT}
+ renderItem={renderComment}
+ showsVerticalScrollIndicator={false}
+ contentContainerStyle={styles.scrollViewContent}
+ getItemLayout={(data, index) => ({
+ length: ITEM_HEIGHT,
+ offset: ITEM_HEIGHT * index,
+ index,
+ })}
+ pagingEnabled
+ />
+ );
+};
+
+const styles = StyleSheet.create({
+ scrollView: {},
+ scrollViewContent: {
+ justifyContent: 'center',
+ },
+});
+
+export default CommentsContainer;