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 './CommentTile'; 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 = ({ screenType, objectId, setCommentsLength, newCommentsAvailable, setNewCommentsAvailable, typeOfComment, setCommentObjectInFocus, commentObjectInFocus, commentId, }) => { const {username: loggedInUsername} = useSelector( (state: RootState) => state.user.user, ); const [commentsList, setCommentsList] = useState([]); const dispatch = useDispatch(); const ref = useRef>(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}) => ( ); return ( 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;