import {useNavigation} from '@react-navigation/native'; import React, {Fragment, useContext, useEffect, useRef, useState} from 'react'; import {Alert, Animated, StyleSheet} from 'react-native'; import {Text, View} from 'react-native-animatable'; import {RectButton, TouchableOpacity} from 'react-native-gesture-handler'; import Swipeable from 'react-native-gesture-handler/Swipeable'; import {useDispatch, useSelector, useStore} from 'react-redux'; import Arrow from '../../assets/icons/back-arrow-colored.svg'; import ClockIcon from '../../assets/icons/clock-icon-01.svg'; import Trash from '../../assets/ionicons/trash-outline.svg'; import {TAGG_LIGHT_BLUE} from '../../constants'; import {ERROR_FAILED_TO_DELETE_COMMENT} from '../../constants/strings'; import {CommentContext} from '../../screens/profile/MomentCommentsScreen'; import { deleteComment, getCommentsCount, handleLikeUnlikeComment, } from '../../services'; import {RootState} from '../../store/rootReducer'; import { CommentThreadType, CommentType, ScreenType, UserType, } from '../../types'; import {getTimePosted, navigateToProfile, normalize} from '../../utils'; import {mentionPartTypes, renderTextWithMentions} from '../../utils/comments'; import {LikeButton} from '../common'; import {ProfilePreview} from '../profile'; 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. */ interface CommentTileProps { commentObject: CommentType | CommentThreadType; screenType: ScreenType; isThread: boolean; shouldUpdateParent: boolean; setShouldUpdateParent: (update: boolean) => void; canDelete: boolean; } const CommentTile: React.FC = ({ commentObject, screenType, setShouldUpdateParent, shouldUpdateParent, canDelete, isThread, }) => { const {setCommentTapped} = useContext(CommentContext); const timePosted = getTimePosted(commentObject.date_created); const [showReplies, setShowReplies] = useState(false); const [showKeyboard, setShowKeyboard] = useState(false); const [shouldUpdateChild, setShouldUpdateChild] = useState(true); const [liked, setLiked] = useState(commentObject.user_reaction !== null); const swipeRef = useRef(null); const {replyPosted} = useSelector((state: RootState) => state.user); const state: RootState = useStore().getState(); const navigation = useNavigation(); const dispatch = useDispatch(); useEffect(() => { if (shouldUpdateParent) { setShouldUpdateChild(true); } }, [shouldUpdateParent]); useEffect(() => { if (replyPosted && !isThread) { if (replyPosted.parent_comment.comment_id === commentObject.comment_id) { setShowReplies(true); } } }, [replyPosted]); const toggleAddComment = () => { setCommentTapped(commentObject); setShowKeyboard(!showKeyboard); }; const toggleReplies = async () => { if (showReplies && isThread) { const comment = (commentObject as CommentThreadType).parent_comment; //To update count of replies in case we deleted a reply comment.replies_count = parseInt( await getCommentsCount(comment.comment_id, true), 10, ); } setShouldUpdateChild(true); setShowReplies(!showReplies); }; /** * Method to compute text to be shown for replies button */ const getRepliesText = (comment: CommentType) => showReplies ? 'Hide' : comment.replies_count > 0 ? `Replies (${comment.replies_count}) ` : 'Replies'; const renderRightAction = (text: string, color: string) => { const pressHandler = async () => { swipeRef.current?.close(); const success = await deleteComment(commentObject.comment_id, isThread); if (success) { setShouldUpdateParent(true); } else { Alert.alert(ERROR_FAILED_TO_DELETE_COMMENT); } }; return ( {text} ); }; const renderRightActions = (_: Animated.AnimatedInterpolation) => canDelete ? ( {renderRightAction('Delete', '#c42634')} ) : ( ); return ( handleLikeUnlikeComment(commentObject, liked)} style={styles.likeButton} /> {renderTextWithMentions({ value: commentObject.comment, styles: styles.comment, partTypes: mentionPartTypes('blue'), onPress: (user: UserType) => navigateToProfile(state, dispatch, navigation, screenType, user), })} {' ' + timePosted} { navigation.navigate('CommentReactionScreen', { comment: commentObject, screenType: screenType, }); }}> {commentObject.user_reaction !== null ? commentObject.reaction_count + (liked ? 0 : -1) : commentObject.reaction_count + (liked ? 1 : 0)} Likes {/* Show replies text only if there are some replies present */} {!isThread && (commentObject as CommentType).replies_count > 0 && ( {getRepliesText(commentObject as CommentType)} )} {/* Show replies if toggle state is true */} {showReplies && ( )} ); }; const styles = StyleSheet.create({ container: { borderBottomWidth: 1, borderColor: 'lightgray', backgroundColor: 'white', flexDirection: 'column', flex: 1, paddingTop: '3%', marginLeft: '5%', paddingBottom: '2%', }, swipeActions: { flexDirection: 'row', }, moreMarginWithThread: { marginLeft: '14%', }, commentHeaderContainer: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', }, likeButton: { marginRight: 10, }, body: { marginLeft: 56, }, comment: { marginBottom: '2%', marginRight: '2%', }, date_time: { color: 'gray', fontSize: normalize(12), }, clockIcon: { width: 12, height: 12, alignSelf: 'center', }, commentInfoContainer: { flexDirection: 'row', marginTop: '3%', justifyContent: 'space-between', alignItems: 'center', }, likeCount: { color: 'black', marginRight: 5, }, row: { flexDirection: 'row', }, repliesTextAndIconContainer: { flexDirection: 'row', alignItems: 'center', paddingLeft: 10, }, repliesText: { color: TAGG_LIGHT_BLUE, fontWeight: '500', fontSize: normalize(12), marginRight: '1%', }, repliesDownArrow: { transform: [{rotate: '270deg'}], marginTop: '1%', }, repliesUpArrow: { transform: [{rotate: '90deg'}], marginTop: '1%', }, 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;