2023-02-16 22:23:59 +00:00
|
|
|
import Link from 'next/link'
|
|
|
|
import { useRouter } from 'next/router'
|
|
|
|
import { useEffect, useState } from 'react'
|
2023-07-24 18:35:05 +00:00
|
|
|
import Badge from 'react-bootstrap/Badge'
|
|
|
|
import Dropdown from 'react-bootstrap/Dropdown'
|
2023-02-16 22:23:59 +00:00
|
|
|
import Countdown from './countdown'
|
2023-08-08 21:04:06 +00:00
|
|
|
import { abbrNum, numWithUnits } from '../lib/format'
|
2023-08-06 19:18:40 +00:00
|
|
|
import { newComments, commentsViewedAt } from '../lib/new-comments'
|
2023-02-16 22:23:59 +00:00
|
|
|
import { timeSince } from '../lib/time'
|
2023-08-10 22:33:47 +00:00
|
|
|
import CowboyHat, { HatTooltip } from './cowboy-hat'
|
2023-02-16 22:23:59 +00:00
|
|
|
import { DeleteDropdownItem } from './delete'
|
|
|
|
import styles from './item.module.css'
|
|
|
|
import { useMe } from './me'
|
|
|
|
import MoreIcon from '../svgs/more-fill.svg'
|
|
|
|
import DontLikeThisDropdownItem from './dont-link-this'
|
|
|
|
import BookmarkDropdownItem from './bookmark'
|
2023-06-01 00:44:06 +00:00
|
|
|
import SubscribeDropdownItem from './subscribe'
|
2023-02-16 22:23:59 +00:00
|
|
|
import { CopyLinkDropdownItem } from './share'
|
2023-08-10 22:33:47 +00:00
|
|
|
import AnonIcon from '../svgs/spy-fill.svg'
|
2023-02-16 22:23:59 +00:00
|
|
|
|
2023-08-08 21:31:43 +00:00
|
|
|
export default function ItemInfo ({
|
|
|
|
item, pendingSats, full, commentsText = 'comments',
|
|
|
|
commentTextSingular = 'comment', className, embellishUser, extraInfo, onEdit, editText
|
|
|
|
}) {
|
2023-02-16 22:23:59 +00:00
|
|
|
const editThreshold = new Date(item.createdAt).getTime() + 10 * 60000
|
|
|
|
const me = useMe()
|
|
|
|
const router = useRouter()
|
|
|
|
const [canEdit, setCanEdit] =
|
|
|
|
useState(item.mine && (Date.now() < editThreshold))
|
|
|
|
const [hasNewComments, setHasNewComments] = useState(false)
|
2023-07-13 03:08:32 +00:00
|
|
|
const [meTotalSats, setMeTotalSats] = useState(0)
|
|
|
|
|
2023-02-16 22:23:59 +00:00
|
|
|
useEffect(() => {
|
2023-05-11 19:34:42 +00:00
|
|
|
if (!full) {
|
|
|
|
setHasNewComments(newComments(item))
|
|
|
|
}
|
2023-02-16 22:23:59 +00:00
|
|
|
}, [item])
|
|
|
|
|
2023-07-13 03:08:32 +00:00
|
|
|
useEffect(() => {
|
|
|
|
if (item) setMeTotalSats(item.meSats + item.meAnonSats + pendingSats)
|
|
|
|
}, [item?.meSats, item?.meAnonSats, pendingSats])
|
|
|
|
|
2023-02-16 22:23:59 +00:00
|
|
|
return (
|
|
|
|
<div className={className || `${styles.other}`}>
|
|
|
|
{!item.position &&
|
|
|
|
<>
|
2023-08-08 21:31:43 +00:00
|
|
|
<span title={`from ${numWithUnits(item.upvotes, {
|
|
|
|
abbreviate: false,
|
|
|
|
unitSingular: 'stacker',
|
|
|
|
unitPlural: 'stackers'
|
|
|
|
})} ${item.mine
|
2023-08-08 21:04:06 +00:00
|
|
|
? `\\ ${numWithUnits(item.meSats, { abbreviate: false })} to post`
|
2023-08-09 22:02:43 +00:00
|
|
|
: `(${numWithUnits(meTotalSats, { abbreviate: false })} from me)`} `}
|
2023-08-08 21:04:06 +00:00
|
|
|
>
|
|
|
|
{numWithUnits(item.sats + pendingSats)}
|
|
|
|
</span>
|
2023-02-16 22:23:59 +00:00
|
|
|
<span> \ </span>
|
|
|
|
</>}
|
|
|
|
{item.boost > 0 &&
|
|
|
|
<>
|
|
|
|
<span>{abbrNum(item.boost)} boost</span>
|
|
|
|
<span> \ </span>
|
|
|
|
</>}
|
2023-08-06 19:18:40 +00:00
|
|
|
<Link
|
|
|
|
href={`/items/${item.id}`} onClick={(e) => {
|
|
|
|
const viewedAt = commentsViewedAt(item)
|
|
|
|
if (viewedAt) {
|
|
|
|
e.preventDefault()
|
|
|
|
router.push(
|
|
|
|
`/items/${item.id}?commentsViewedAt=${viewedAt}`,
|
|
|
|
`/items/${item.id}`)
|
|
|
|
}
|
2023-08-08 21:04:06 +00:00
|
|
|
}} title={numWithUnits(item.commentSats)} className='text-reset position-relative'
|
2023-08-06 19:18:40 +00:00
|
|
|
>
|
2023-08-08 21:31:43 +00:00
|
|
|
{numWithUnits(item.ncomments, {
|
|
|
|
abbreviate: false,
|
|
|
|
unitPlural: commentsText,
|
|
|
|
unitSingular: commentTextSingular
|
|
|
|
})}
|
2023-08-06 18:21:38 +00:00
|
|
|
{hasNewComments &&
|
|
|
|
<span className={styles.notification}>
|
|
|
|
<span className='invisible'>{' '}</span>
|
|
|
|
</span>}
|
2023-02-16 22:23:59 +00:00
|
|
|
</Link>
|
|
|
|
<span> \ </span>
|
|
|
|
<span>
|
2023-07-24 18:35:05 +00:00
|
|
|
<Link href={`/${item.user.name}`}>
|
2023-08-10 22:33:47 +00:00
|
|
|
@{item.user.name}<span> </span>
|
|
|
|
{item.user.name === 'anon'
|
|
|
|
? <HatTooltip overlayText='so sneaky!'><span><AnonIcon className='fill-grey align-middle' height={12} width={12} /></span></HatTooltip>
|
|
|
|
: <CowboyHat className='fill-grey' user={item.user} height={12} width={12} />}
|
2023-07-23 15:08:43 +00:00
|
|
|
{embellishUser}
|
2023-02-16 22:23:59 +00:00
|
|
|
</Link>
|
|
|
|
<span> </span>
|
2023-07-23 15:08:43 +00:00
|
|
|
<Link href={`/items/${item.id}`} title={item.createdAt} className='text-reset' suppressHydrationWarning>
|
|
|
|
{timeSince(new Date(item.createdAt))}
|
2023-02-16 22:23:59 +00:00
|
|
|
</Link>
|
|
|
|
{item.prior &&
|
|
|
|
<>
|
|
|
|
<span> \ </span>
|
2023-07-23 15:08:43 +00:00
|
|
|
<Link href={`/items/${item.prior}`} className='text-reset'>
|
|
|
|
yesterday
|
2023-02-16 22:23:59 +00:00
|
|
|
</Link>
|
|
|
|
</>}
|
|
|
|
</span>
|
2023-05-05 17:38:56 +00:00
|
|
|
{item.subName &&
|
|
|
|
<Link href={`/~${item.subName}`}>
|
2023-07-24 18:35:05 +00:00
|
|
|
{' '}<Badge className={styles.newComment} bg={null}>{item.subName}</Badge>
|
2023-05-02 16:55:10 +00:00
|
|
|
</Link>}
|
2023-02-16 22:23:59 +00:00
|
|
|
{(item.outlawed && !item.mine &&
|
2023-07-23 15:08:43 +00:00
|
|
|
<Link href='/recent/outlawed'>
|
2023-07-24 18:35:05 +00:00
|
|
|
{' '}<Badge className={styles.newComment} bg={null}>outlawed</Badge>
|
2023-05-02 16:55:10 +00:00
|
|
|
</Link>) ||
|
2023-07-23 15:08:43 +00:00
|
|
|
(item.freebie &&
|
|
|
|
<Link href='/recent/freebies'>
|
2023-07-24 18:35:05 +00:00
|
|
|
{' '}<Badge className={styles.newComment} bg={null}>freebie</Badge>
|
2023-02-16 22:23:59 +00:00
|
|
|
</Link>
|
2023-05-02 16:55:10 +00:00
|
|
|
)}
|
2023-02-16 22:23:59 +00:00
|
|
|
{canEdit && !item.deletedAt &&
|
|
|
|
<>
|
|
|
|
<span> \ </span>
|
|
|
|
<span
|
|
|
|
className='text-reset pointer'
|
|
|
|
onClick={() => onEdit ? onEdit() : router.push(`/items/${item.id}/edit`)}
|
|
|
|
>
|
|
|
|
{editText || 'edit'}
|
|
|
|
<Countdown
|
|
|
|
date={editThreshold}
|
|
|
|
onComplete={() => {
|
|
|
|
setCanEdit(false)
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
</span>
|
|
|
|
</>}
|
|
|
|
<ItemDropdown>
|
|
|
|
<CopyLinkDropdownItem item={item} />
|
2023-02-16 23:07:20 +00:00
|
|
|
{me && <BookmarkDropdownItem item={item} />}
|
2023-06-01 00:44:06 +00:00
|
|
|
{me && item.user.id !== me.id && <SubscribeDropdownItem item={item} />}
|
2023-02-16 23:07:20 +00:00
|
|
|
{item.otsHash &&
|
2023-07-23 15:08:43 +00:00
|
|
|
<Link href={`/items/${item.id}/ots`} className='text-reset dropdown-item'>
|
|
|
|
ots timestamp
|
|
|
|
</Link>}
|
2023-02-16 22:23:59 +00:00
|
|
|
{me && !item.meSats && !item.position && !item.meDontLike &&
|
|
|
|
!item.mine && !item.deletedAt && <DontLikeThisDropdownItem id={item.id} />}
|
|
|
|
{item.mine && !item.position && !item.deletedAt &&
|
|
|
|
<DeleteDropdownItem itemId={item.id} />}
|
|
|
|
</ItemDropdown>
|
2023-02-16 23:14:14 +00:00
|
|
|
{extraInfo}
|
2023-02-16 22:23:59 +00:00
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
export function ItemDropdown ({ children }) {
|
|
|
|
return (
|
2023-07-24 18:35:05 +00:00
|
|
|
<Dropdown className={`pointer ${styles.dropdown}`} as='span'>
|
|
|
|
<Dropdown.Toggle variant='success' as='a'>
|
|
|
|
<MoreIcon className='fill-grey ms-1' height={16} width={16} />
|
2023-02-16 22:23:59 +00:00
|
|
|
</Dropdown.Toggle>
|
|
|
|
<Dropdown.Menu>
|
|
|
|
{children}
|
|
|
|
</Dropdown.Menu>
|
|
|
|
</Dropdown>
|
|
|
|
)
|
|
|
|
}
|