import React, { useMemo, useRef, useState } from 'react'; import { Text, Pressable, FlatList, StyleSheet, View, Share, Alert, Linking, Animated, PanResponder } from 'react-native'; import { Button, Card, Chip } from 'react-native-paper'; import API from './../API.js'; import UserName from './UserName.js'; import Media from './Media.js'; import Comment from "./Comment"; import NewComment from './NewComment.js'; import Moment from 'moment'; import { useSnapshot } from 'valtio'; import GlobalState from '../contexts/GlobalState.js'; import i18n from "../i18nMessages.js"; import ProfilePhotoCircle from './ProfilePhotoCircle.js'; import { posthog } from './../PostHog.js'; import { useNavigation } from '@react-navigation/native'; import ParsedText from 'react-native-parsed-text'; let Post = (props) => { const gState = useSnapshot(GlobalState); const viewer = gState.me; let [showCommentsB, changeshowCommentsB] = useState(props.showComments || false); let [post, changePost] = useState(props.post); const [deleted, setDeleted] = useState(false); let [likes, changeLikes] = useState(Object.keys(post.reactions).length); let [bookmarked, changeBookmarked] = useState(post.bookmarks && post.bookmarks.includes(viewer._id)); const isOwner = String(post.profileid || '') === String(viewer?._id || ''); const swipeX = useRef(new Animated.Value(0)).current; const SWIPE_WIDTH = 86; let toProfileText = post.toProfile && post.toProfile !== post.profileid ? : undefined; let cleanContent = post.content.replace(/@[A-z]+:.+\w/g, '').trim(); const navigation = useNavigation(); //cleanContent = convertLinks(cleanContent); const newComentAdded = (commentData) => { let newPostObj = { ...post }; newPostObj.comments.push(commentData); changePost(newPostObj); }; const newPostReaction = () => { let newPostObj = { ...post }; if (!newPostObj.reactions[viewer._id]) { changeLikes(likes + 1); newPostObj.reactions[viewer._id] = { type: "like" }; API.newPostReaction(post._id); posthog.capture( 'post_clicked', { post_id: post._id, } ); } else { changeLikes(likes - 1); delete newPostObj.reactions[viewer._id]; API.removePostReaction(viewer._id); } changePost(newPostObj); } const newPostBookmark = () => { if (!post.bookmarks || !post.bookmarks.includes(viewer._id)) { changeBookmarked(true); if (!post.bookmarks) post.bookmarks = []; post.bookmarks.push(viewer._id); API.newPostBookmark(post._id); } else { changeBookmarked(false); post.bookmarks = post.bookmarks.filter(id => id != viewer._id); API.removePostBookmark(post._id) } } const renderComment = ({ item }) => ( ); const handleTagPress = (tag) => { // Alert.alert("tag pressed", `You pressed the tag: ${tag}`); // You can navigate to another screen or perform any other action here //remove hastag from tag tag = tag.replace("#", ""); navigation.navigate("Tags", { tag: tag }); }; const handleLinkPress = (url) => { Linking.canOpenURL(url) .then((supported) => { if (supported) { Linking.openURL(url); } else { Alert.alert('Error', 'Unable to open the link.'); } }) .catch((err) => console.error('An error occurred', err)); }; const handleLinkLongPress = (url) => { Share.share({ url: url }); }; const closeSwipe = () => { Animated.spring(swipeX, { toValue: 0, useNativeDriver: true }).start(); }; const deletePost = async () => { const result = await API.deletePost(post._id); if (result?.status !== "ok") { Alert.alert("Could not delete post", result?.status || "Please try again."); return closeSwipe(); } setDeleted(true); }; const confirmDelete = () => { Alert.alert( "Delete post?", "This action cannot be undone.", [ { text: "Cancel", style: "cancel", onPress: closeSwipe }, { text: "Delete", style: "destructive", onPress: deletePost }, ] ); }; const panResponder = useMemo(() => PanResponder.create({ onMoveShouldSetPanResponder: (_, gestureState) => isOwner && Math.abs(gestureState.dx) > 8 && Math.abs(gestureState.dx) > Math.abs(gestureState.dy), onPanResponderMove: (_, gestureState) => { if (gestureState.dx > 0) { swipeX.setValue(0); return; } swipeX.setValue(Math.max(gestureState.dx, -SWIPE_WIDTH)); }, onPanResponderRelease: (_, gestureState) => { const open = gestureState.dx < -SWIPE_WIDTH / 2; Animated.spring(swipeX, { toValue: open ? -SWIPE_WIDTH : 0, useNativeDriver: true, }).start(); }, onPanResponderTerminate: closeSwipe, }), [isOwner, swipeX]); if (deleted) return null; const postCard = ( {!post.nonOrganicType ? {toProfileText} { if (cleanContent.length > 10) { Share.share({ message: cleanContent }); } }}> {cleanContent} : {i18n.t("message.news")} {cleanContent} } {" " + Moment(post.createdAt).fromNow()} {showCommentsB && } { showCommentsB && item.createdAt} /> } ); if (!isOwner) return postCard; return ( Delete {postCard} ); } export default React.memo(Post); const styles = StyleSheet.create({ userName: { fontSize: 14, fontWeight: 'bold', marginBottom: 5, fontSize: 17, }, card: { margin: 0, backgroundColor: "#FAFAFA", borderRadius: 0, marginBottom: 2, padding: 0 }, swipeWrap: { position: "relative", backgroundColor: "#edf2f7", }, deleteActionWrap: { position: "absolute", right: 0, top: 0, bottom: 2, width: 86, justifyContent: "center", alignItems: "center", backgroundColor: "#b3261e", }, deleteActionBtn: { width: "100%", height: "100%", justifyContent: "center", alignItems: "center", }, deleteActionText: { color: "#fff", fontWeight: "700", }, comment: { margin: 8, marginTop: 0, padding: 8 }, text: { fontSize: 16, padding: 3, paddingLeft: 40 }, tag: { color: '#77B5FE', textDecorationLine: 'underline', }, link: { color: '#77B5FE', textDecorationLine: 'underline', }, });