import Item from './item' import ItemJob from './item-job' import Reply from './reply' import Comment from './comment' import Text, { ZoomableImage } from './text' import Comments from './comments' import styles from '../styles/item.module.css' import itemStyles from './item.module.css' import { NOFOLLOW_LIMIT } from '../lib/constants' import { useMe } from './me' import Button from 'react-bootstrap/Button' import { TwitterTweetEmbed } from 'react-twitter-embed' import YouTube from 'react-youtube' import useDarkMode from './dark-mode' import { useEffect, useState } from 'react' import Poll from './poll' import { commentsViewed } from '../lib/new-comments' import Related from './related' import PastBounties from './past-bounties' import Check from '../svgs/check-double-line.svg' import Share from './share' import Toc from './table-of-contents' import Link from 'next/link' import { RootProvider } from './root' import { IMGPROXY_URL_REGEXP } from '../lib/url' import { numWithUnits } from '../lib/format' function BioItem ({ item, handleClick }) { const me = useMe() if (!item.text) { return null } return ( <> {me?.name === item.user.name &&
} ) } function TweetSkeleton () { return (
) } function ItemEmbed ({ item }) { const [darkMode] = useDarkMode() const [overflowing, setOverflowing] = useState(false) const [show, setShow] = useState(false) const twitter = item.url?.match(/^https?:\/\/(?:twitter|x)\.com\/(?:#!\/)?\w+\/status(?:es)?\/(?\d+)/) if (twitter?.groups?.id) { return (
} onLoad={() => setOverflowing(true)} /> {overflowing && !show && }
) } const youtube = item.url?.match(/(https?:\/\/)?((www\.)?(youtube(-nocookie)?|youtube.googleapis)\.com.*(v\/|v=|vi=|vi\/|e\/|embed\/|user\/.*\/u\/\d+\/)|youtu\.be\/)(?[_0-9a-z-]+)((?:\?|&)(?:t|start)=(?\d+))?/i) if (youtube?.groups?.id) { return (
) } if (item.url?.match(IMGPROXY_URL_REGEXP)) { return } return null } function FwdUsers ({ forwards }) { return (
zaps forwarded to {' '} {forwards.map((fwd, index, arr) => ( @{fwd.user.name} {` (${fwd.pct}%)`}{index !== arr.length - 1 && ' '} ))}
) } function TopLevelItem ({ item, noReply, ...props }) { const ItemComponent = item.isJob ? ItemJob : Item return ( } belowTitle={item.forwards && item.forwards.length > 0 && } {...props} >
{item.text && } {item.url && } {item.poll && } {item.bounty &&
{item.bountyPaidTo?.length ? (
{numWithUnits(item.bounty, { abbreviate: false })} paid {item.bountyPaidTo.length > 1 && {item.bountyPaidTo.length} times}
) : (
{numWithUnits(item.bounty, { abbreviate: false })} bounty
)}
}
{!noReply && <> {!item.position && !item.isJob && !item.parentId && !item.bounty > 0 && } {item.bounty > 0 && } }
) } function ItemText ({ item }) { return {item.searchText || item.text} } export default function ItemFull ({ item, bio, rank, ...props }) { useEffect(() => { commentsViewed(item) }, [item.lastCommentAt]) return ( <> {rank ? (
{rank}
) :
} {item.parentId ? : (
{bio ? : }
)} {item.comments &&
}
) }