import Item from './item' import ItemJob from './item-job' import Reply from './reply' import Comment from './comment' import Text, { SearchText } from './text' import MediaOrLink from './media-or-link' import Comments from './comments' import styles from '@/styles/item.module.css' import itemStyles from './item.module.css' import { useMe } from './me' import Button from 'react-bootstrap/Button' import { useEffect } 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 { decodeProxyUrl, IMGPROXY_URL_REGEXP, parseEmbedUrl } from '@/lib/url' import { numWithUnits } from '@/lib/format' import { useQuoteReply } from './use-quote-reply' import { UNKNOWN_LINK_REL } from '@/lib/constants' import classNames from 'classnames' import { CarouselProvider } from './carousel' import Embed from './embed' function BioItem ({ item, handleClick }) { const { me } = useMe() if (!item.text) { return null } return ( <> {me?.name === item.user.name &&
} ) } function ItemEmbed ({ url, imgproxyUrls }) { const provider = parseEmbedUrl(url) if (provider) { return (
) } if (imgproxyUrls) { const src = IMGPROXY_URL_REGEXP.test(url) ? decodeProxyUrl(url) : url const srcSet = imgproxyUrls?.[url] 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 const { ref: textRef, quote, quoteReply, cancelQuote } = useQuoteReply({ text: item.text }) return ( } belowTitle={item.forwards && item.forwards.length > 0 && } {...props} >
{item.text && } {item.url && !item.outlawed && } {item.poll && } {item.bounty &&
{item.bountyPaidTo?.length ? (
{numWithUnits(item.bounty, { abbreviate: false, format: true })} paid {item.bountyPaidTo.length > 1 && {new Set(item.bountyPaidTo).size} times}
) : (
{numWithUnits(item.bounty, { abbreviate: false, format: true })} bounty
)}
}
{!noReply && <> { // Don't show related items for Saloon items (position is set but no subName) (!item.position && item.subName) && // Don't show related items for jobs !item.isJob && // Don't show related items for child items !item.parentId && // Don't show related items for deleted items !item.deletedAt && // Don't show related items for items with bounties, show past bounties instead !(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 &&
}
) }