import {EyeSlashIcon, FlagIcon} from '@heroicons/react/24/outline' import {ArrowUturnLeftIcon, EllipsisHorizontalIcon} from '@heroicons/react/24/solid' import {Editor} from '@tiptap/react' import clsx from 'clsx' import {type Comment, MAX_COMMENT_LENGTH, ReplyToUserInfo} from 'common/comment' import {buildArray} from 'common/util/array' import {ChevronDown, ChevronUp} from 'lucide-react' import {memo, ReactNode, useEffect, useRef, useState} from 'react' import {toast} from 'react-hot-toast' import {Button, IconButton} from 'web/components/buttons/button' import {ReportModal} from 'web/components/buttons/report-button' import {CommentInputTextArea} from 'web/components/comments/comment-input' import DropdownMenu from 'web/components/comments/dropdown-menu' import {ReplyToggle} from 'web/components/comments/reply-toggle' import {Col} from 'web/components/layout/col' import {Row} from 'web/components/layout/row' import {RelativeTimestamp} from 'web/components/relative-timestamp' import {Avatar} from 'web/components/widgets/avatar' import {Content, useTextEditor} from 'web/components/widgets/editor' import {Tooltip} from 'web/components/widgets/tooltip' import {UserLink} from 'web/components/widgets/user-link' import {useAdmin} from 'web/hooks/use-admin' import {useEvent} from 'web/hooks/use-event' import {useProfileByUserId} from 'web/hooks/use-profile' import {useUser} from 'web/hooks/use-user' import {api} from 'web/lib/api' import {firebaseLogin, User} from 'web/lib/firebase/users' import {useT} from 'web/lib/locale' import {track} from 'web/lib/service/analytics' import {safeLocalStorage} from 'web/lib/util/local' import {scrollIntoViewCentered} from 'web/lib/util/scroll' export function ProfileProfileCommentThread(props: { onUser: User threadComments: Comment[] parentComment: Comment trackingLocation: string collapseMiddle?: boolean inTimeline?: boolean idInUrl?: string showReplies?: boolean className?: string }) { const { onUser, threadComments, parentComment, collapseMiddle, trackingLocation, idInUrl, showReplies, className, } = props const [replyToUserInfo, setReplyToUserInfo] = useState() const idInThisThread = idInUrl && threadComments.map((comment) => comment.id).includes(idInUrl) const [seeReplies, setSeeReplies] = useState( !parentComment.hidden && (showReplies || !!idInThisThread), ) const onSeeRepliesClick = useEvent(() => setSeeReplies(!seeReplies)) const clearReply = useEvent(() => setReplyToUserInfo(undefined)) const onReplyClick = useEvent((comment: Comment) => { setSeeReplies(true) setReplyToUserInfo({id: comment.id, username: comment.userUsername}) }) const [collapseToIndex, setCollapseToIndex] = useState( collapseMiddle && threadComments.length > 2 ? threadComments.length - 2 : Infinity, ) return ( {seeReplies && threadComments .slice(0, collapseToIndex) .map((comment) => ( ))} {seeReplies && threadComments.length > collapseToIndex && ( )} {replyToUserInfo && (
)} ) } const ProfileComment = memo(function FeedComment(props: { onUser: User comment: Comment trackingLocation: string highlighted?: boolean onReplyClick?: (comment: Comment) => void children?: ReactNode isParent?: boolean }) { const {onUser, highlighted, onReplyClick, children, trackingLocation, isParent} = props const ref = useRef(null) const [comment, setComment] = useState(props.comment) const {userUsername, userAvatarUrl, userId, hidden} = comment const isOwner = onUser.id === userId const profile = useProfileByUserId(userId) useEffect(() => { if (highlighted && ref.current) { scrollIntoViewCentered(ref.current) } }, [highlighted]) return ( {!isParent && (
)}
setComment({...comment, hidden: !comment.hidden})} /> {hidden ? ( Comment deleted ) : ( )} {children} ) }) const ParentProfileComment = memo(function ParentFeedComment(props: { onUser: User comment: Comment highlighted?: boolean seeReplies: boolean numReplies: number onReplyClick?: (comment: Comment) => void onSeeReplyClick: () => void trackingLocation: string }) { const { onUser, comment, highlighted, onReplyClick, onSeeReplyClick, seeReplies, numReplies, trackingLocation, } = props return ( ) }) function DotMenu(props: {onUser: User; comment: Comment; onHide: () => void}) { const {comment, onHide, onUser} = props const [isModalOpen, setIsModalOpen] = useState(false) const user = useUser() const isCurrentUser = user?.id === comment.userId const isOwner = onUser.id === user?.id const isAdmin = useAdmin() return ( <>