Sherlock / app / (tabs) / (profile) / comments.tsx
comments.tsx
Raw
import React, { useEffect, useState } from "react";
import { View, Text } from '../../../components/Themed';
import {StyleSheet, Touchable, KeyboardAvoidingView, Platform, LayoutAnimation, ActivityIndicator} from "react-native";
import global, { userLocation, width } from "../../../constants/global";
import Colors from "../../../constants/Colors";
import { getIncidentEmoji } from "../../../constants/emojis";
import { TouchableOpacity, Keyboard } from "react-native";
import { Badge, BadgeText, get, Icon, Input, InputField, InputSlot, Menu, MenuItem, MenuItemLabel, Pressable, ScrollView, SectionList, set, TrashIcon, VStack } from "@gluestack-ui/themed";
import { Ionicons, MaterialCommunityIcons, Octicons } from "@expo/vector-icons";
import { createComment, deleteComment, deleteEntity, getComments, getCommentsAfter, getEntityCounts, getInitPosts, getUserAlias, getUserComments, hasLiked, likeEntity, unlikeEntity, dislikeEntity, dislikeComment, deleteCommentLike, likeComment, hasLikedComment, getAllUserComments, getPost } from "../../../components/backend";
import constants from 'expo-constants'
import { formatnum } from "../../../components/postListView";
import { FlatList, RefreshControl } from "react-native-gesture-handler";
import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';
import { FeedContext } from "../../../components/feedContext";
import { router, useLocalSearchParams, useNavigation } from "expo-router";
import { useSettings } from "../../../components/appSettingsContext";
import { UserFeedContext } from "../../../components/userFeedContext";



export default function CommentsScreen() {
    const route = useNavigation()
    
    const [comments, setComments] = React.useState<any>([]);
    const [refreshing, setRefreshing] = React.useState(false);
    const [commentPH, setCommentPH] = React.useState("");
    const [hasFetched, setHasFetched] = useState(false);
    const [userComment, setUserComment] = React.useState("");
    const [menuSelected, setMenuSelected] = React.useState(new Set([]) as any);
    const settings = useSettings().settings;



    useEffect(()=>{
        getAllUserComments().then((comments)=>{
            console.log(comments)
            setComments(comments)
            setHasFetched(true)
        }).catch((e)=>{
            console.error('Error getting user comments: ',e)
        })
    },[])

    const RenderComment = ({item}:any) => {
            const [commentLiked, setCommentLiked] = React.useState(false);
            const [commentDisliked, setCommentDisliked] = React.useState(false);
            // Sets the emoji for the comment
            const commentEmoji = getIncidentEmoji(item.alias, '6', true);
    
    
            // Sets the comment liked state
            useEffect(()=>{
                hasLikedComment(item.id).then((res) => {
                    switch(res.sentiment){
                        case "like":
                            setCommentLiked(true);
                            break;
                        case "dislike":
                            setCommentDisliked(true);
                            break;
                        default:
                            setCommentLiked(false);
                            setCommentDisliked(false);
                    }
                })
            },[])
    
            return(
                <Pressable 
                    style={styles.commentContentContainer}
                    onPress={()=>{
                        getPost(item.eid).then((post)=>{
                            post.likeCount=0;
                            post.commentCount=0;
                            global.passedPost = post;

                            router.push('/(profile)/post')

                            console.log(post)
                        }).catch((e)=>{
                            console.error('Error fetching post by id:',e)
                        })
                    }}

                >
                    {/* Comment header */}
                    <View style={styles.commentContentHeader}>
                        {/* Emoji avatar */}
                        <View style={[styles.emojiContainer,{backgroundColor:Colors.map["class"+commentEmoji[1] as keyof typeof Colors.map]}, styles.commentAvatar]}>
                            <Text adjustsFontSizeToFit numberOfLines={1} style={styles.emoji}>{commentEmoji[0]}</Text>
                        </View>
    
                        <VStack style={styles.commentTitleHeader}>
                                {settings.showOP&&<Badge size="md" borderRadius={"$lg"}backgroundColor={Colors.dark.alertBackground}action="info" width={'25%'}>
                                    <BadgeText color={Colors.dark.redBright} fontWeight={"$bold"}>Yours</BadgeText>
                                </Badge>}
    
                            <Text adjustsFontSizeToFit numberOfLines={item.isOP?1:2} style={styles.commentTitle}>{item.alias}</Text>
                        </VStack>
    
                        <Menu
                            placement="bottom right"
                            selectionMode="single"
                            shadowColor="transparent"
                            maxWidth={global.width*0.3}
                            backgroundColor={Colors.dark.tabBg}
                            selectedKeys={menuSelected}
                            onSelectionChange={(keys) => {
                                setMenuSelected(keys)
                                //@ts-ignore
                                switch (keys.currentKey){
                                    case "Report":
                                        console.log("Report clicked");
                                        break;
                                    case "Delete":
                                        deleteComment(item.id).then((res) => {
                                            console.log("Deleted comment: ", res);
                                            let t = [...comments];
                                            t = t.filter((c:any) => c.id!=item.id);
                                            setComments(t);
                                        }).catch((err) => {
                                            console.log("Error deleting comment: ", err);
                                        })
                                        break;
                                    default:
                                        console.log("Default clicked");
                                }
                            }}
                            closeOnSelect={true}
                            trigger={({ ...triggerProps }) => {
                                return (
                                <Pressable
                                    {...triggerProps}
                                    style={styles.menu}
                                    >
                                        <MaterialCommunityIcons style={styles.menuIcon} name="dots-vertical" size={24} color={Colors.dark.text} />
                                    </Pressable>
                                )
                            }}
                        >
                            <MenuItem key="Delete" textValue="Delete" $active-bgColor={Colors.dark.backgroundModal} >
                                <MaterialCommunityIcons name="delete" size={24} color={Colors.dark.redBright} />
                                <MenuItemLabel size="sm" color={Colors.dark.text}>Delete</MenuItemLabel>
                            </MenuItem>
                        </Menu>
                            
                    </View>
                    
                    <Text style={styles.commentText}>{item.body}</Text>
                    
                    {/* Comment Icons */}
                    <View style={styles.commentFooter}>
                        {/* Comment timestamp */}
                        <Text style={styles.commentTime}>{dayjs(item.created_at).fromNow()}</Text>
    
                        {/* Like buttons */}
                        <View style={styles.voteContainer}>
    
                            <Ionicons name="chevron-expand-sharp" size={25} color={Colors.dark.redBright} style={styles.likeicon} />
    
                            <Text style={styles.voteNumber}>
                                {formatnum(item.likes)}
                            </Text>
                        </View>
                        {/* Comment text */}
                    </View>
    
                </Pressable>
            )
        }

        const renderFooter = () => {
            if(comments.length>10){
                return(
                    <Text style={[styles.body, {fontSize:15}]}>Congrats, you made it to the bottom!</Text>
                )
            }
        }

    return (
        <View style={styles.container}>
            <FlatList
                data={comments}
                renderItem={({item}) => (
                    <RenderComment item={item} />
                )}

                ListEmptyComponent={
                    <View>
                        {hasFetched&&<View style={{flex:1, justifyContent:'center', alignItems:'center', backgroundColor:Colors.dark.tabBg}}>
                            <Text style={styles.noComment}>You have not made any comments.  😔</Text>
                        </View>}
        
                        {!hasFetched&&<View style={{flex:1, justifyContent:'center', alignItems:'center', backgroundColor:Colors.dark.tabBg}}>
                            <ActivityIndicator size="large" color={Colors.dark.cyan} />
                            <Text style={styles.noComment}>Loading comments...</Text>
                        </View>}
                    </View>
                }

                ListFooterComponent={renderFooter}
                ListFooterComponentStyle={{marginBottom: 50}}

                refreshControl={
                    <RefreshControl
                    colors={[Colors.dark.cyan, Colors.dark.redBright]}
                    progressBackgroundColor={Colors.dark.backgroundProfile}
                    refreshing={refreshing}
                    onRefresh={()=>{
                        setRefreshing(true)
                        getAllUserComments().then((res) => {
                            setComments(res);
                            setRefreshing(false)
                        }).catch((err) => {
                            console.log("Error getting comments: ", err);
                        })
                        
                    }}
    
                    />
                }

            >

            </FlatList>
        </View>
    )
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        alignItems: 'center',
        backgroundColor:Colors.dark.tabBg
    },
    noComment:{
            fontSize: 20,
            color: Colors.dark.text,
            textAlign: 'center',
            marginTop: 10,
            alignSelf: 'center',
            width: global.width*.6,
            marginBottom: global.height*.1,
    
        },
        // commentHeaderIcons:{
        //     flexDirection: 'column',
        //     backgroundColor: Colors.dark.background,
        //     columnGap: 10,
        //     justifyContent: 'space-between',
        //     // position: 'absolute',
        //     width:'10%',
        //     height: global.height*0.1,
        //     zIndex: 10,
        // },
        commentText:{
            fontSize: 18,
            color: Colors.dark.text,
            backgroundColor: Colors.dark.background,
            marginLeft: global.height*0.095,
            marginRight: 10,
            width: '68%',
        },
        commentFooter:{
            flexDirection:'row',
            width:'100%',
            marginTop: 10,
        },
        voteContainer:{
            flexDirection: 'row',
            width: '20%',
            height: '100%',
            justifyContent: 'space-evenly',
            backgroundColor: Colors.dark.background,
            marginLeft: 'auto',
            alignSelf:'flex-end'
        },
        voteNumber:{
            textAlign:'center',
            fontWeight: 'bold',
            fontSize:18,
        },
        commentTime:{
            fontSize: 12,
            color: Colors.dark.text,
            alignSelf: 'flex-start',
            backgroundColor: Colors.dark.background,
            marginLeft:10,
            height: '100%',
            textAlignVertical: 'center',
        },
        commentLikeButton:{
            alignSelf: 'flex-end',
            justifyContent: 'space-evenly',
            alignContent:'space-evenly',
            // backgroundColor:'red'
        },
        commentTitle:{
            fontSize: 20,
            fontWeight: 'bold',
            color: Colors.dark.cyan,
            alignSelf: 'center',
            width: '100%',
            textAlign: 'left',
        },
        commentTitleHeader:{
            alignSelf: 'center',
            width: '70%',
            maxHeight: global.height*0.07,
        },
        commentContentHeader:{
            flexDirection: 'row',
            backgroundColor: Colors.dark.background,
            padding: 10,
            columnGap: 10,
            justifyContent:'center',
        },
        commentContentContainer:{
            flex:1,
            flexDirection: 'column',
            width: global.width*0.95,
            backgroundColor: Colors.dark.background,
            minHeight: global.height*0.15,
            alignSelf: 'center',
            borderRadius: 10,
            padding:5,
            marginBottom: 15,
            paddingBottom:10,
            paddingRight: 10,
        },
        commentAvatar:{
            alignSelf: 'flex-end',
            width: global.height*0.07,
            height: global.height*0.07,
            borderWidth:3,
        },
        root:{
            flex:1,
            height: global.height,
            width: global.width,
            // paddingBottom:70,
            backgroundColor: Colors.dark.tabBg,
        },
        sendButtonIcon:{
            marginRight: 10,
        },
        commentInput:{
            width: global.width*0.95,
            alignSelf: 'center',
        },
        commentContainer:{
            flex:1,
            position: 'static',
            width: global.width,
            maxHeight: 115,
            zIndex: 10,
            backgroundColor: Colors.dark.tabBg,
            marginBottom: 10,
            
        },
        commentHeader:{
            paddingHorizontal:5,
            paddingVertical:2,
            flexDirection: 'row',
            backgroundColor: Colors.dark.tabBg,
        },
        wrapper:{
            // height: global.height,
            width: global.width,
            backgroundColor: Colors.dark.tabBg,
            padding:0,
            flex:1,
            paddingTop:5,
        },
        content:{
            backgroundColor: Colors.dark.tabBg,
            flexDirection: 'column',
            width:global.width,
            minHeight: global.height*0.08,
            flex:1,
            overflow: 'hidden',
            padding:1,
            marginBottom: 10,
        },
        header:{
            backgroundColor: Colors.dark.tabBg,
            flexDirection: 'row',
            width: global.width,
            columnGap: 5,
            padding: 10,
            flex:1,
            marginTop:0,
            paddingTop:0,
    
        },
        headerDivide:{
            width: '90%',
        },
        title:{
            fontSize: 30,
            fontWeight: 'bold',
            color: Colors.dark.cyan,
            backgroundColor: Colors.dark.tabBg,
            textAlignVertical:'bottom',
            width:'70%'
        },
        emojiContainer:{
            justifyContent: 'center',
            alignItems: 'center',
            height: global.height*.08,
            width: global.height*.08,
            borderWidth:3,
            borderColor:Colors.dark.backgroundProfile,
            borderRadius: 10,
            // alignSelf:"flex-start",
        },
        emoji:{
            fontSize: 50,
        },
        separator: {
            height: 2,
            width: '80%',
            alignSelf: "flex-start",
            justifyContent: 'flex-start',
            marginBottom:5,
            backgroundColor: Colors.dark.darkText,
            borderRadius: 10,
        },
        footerdivide:{
            alignSelf: 'center',
            height:1,
            backgroundColor: Colors.dark.darkText,
        },
        body:{
            fontSize: 20,
            fontWeight: 'bold',
            color: Colors.dark.text,
            textAlign: 'center',
            backgroundColor: Colors.dark.tabBg,
            width:global.width*0.9*0.88,
            alignSelf:'center',
            textAlignVertical:'center',
        },
        footer:{
            backgroundColor: Colors.dark.tabBg,
            width: width*0.9,
            height: '20%',
            bottom:0,
            left:0,
            flexDirection: 'row',
            paddingBottom:0,
            flex:1,
            justifyContent: 'space-between',
            paddingHorizontal: 10,
            alignSelf: 'center',
        },
        footerText:{
            fontSize: 12,
            fontWeight: 'bold',
            color: Colors.dark.text,
            // textAlign: 'left',
            alignSelf:'flex-start',
            backgroundColor: Colors.dark.tabBg,
            textAlignVertical:'bottom',
        },
        time:{
            flexDirection: 'column',
            rowGap: 2,
            width: '20%',
            height: '100%',
            justifyContent: 'center',
            backgroundColor: Colors.dark.tabBg,
            marginBottom: 10,
        },
        timetext:{
            textAlign:'center',
            justifyContent:'center',
            alignSelf:'center',
    
        },
        likeicon:{
            alignSelf:'center',
    
        },
        commenticon:{
            alignSelf:'center',
            transform: 'scaleX(-1)',
        },
        iconcontainer:{
            flex:1,
            flexDirection: 'row',
            width: '27%',
            height: '100%',
            justifyContent: 'center',
            backgroundColor: Colors.dark.tabBg,
        },
        icontext:{
            fontSize: 20,
            textAlign:'center',
            alignSelf:'center',
            justifyContent:'center',
        },
        postDivide:{
            marginTop: 10,
            width: global.width*0.98,
            backgroundColor: Colors.dark.darkText,
            height: 1,
            alignSelf: 'center',
        },
        menu:{
            backgroundColor: Colors.dark.background,
            justifyContent: 'center',
        },
        menuIcon:{
            width:'100%',
        },
        headertitlecontainer:{
                flexDirection: 'column',
                width: global.width*0.9-global.height*.1-global.width*0.08,
                backgroundColor: Colors.dark.tabBg,
                height: global.height*.08,
                justifyContent: 'center',
            },
})