inform user when there are new comments

This commit is contained in:
keyan 2022-09-02 11:53:44 -05:00
parent 0f5fc31803
commit 297270f34d
6 changed files with 64 additions and 4 deletions

View File

@ -129,6 +129,9 @@ export default function Header ({ sub }) {
}
}
const showJobIndicator = sub !== 'jobs' && (!me || me.noteJobIndicator) &&
(!lastCheckedJobs || lastCheckedJobs < subLatestPost?.subLatestPost)
const NavItems = ({ className }) => {
return (
<>
@ -150,7 +153,7 @@ export default function Header ({ sub }) {
jobs
</Nav.Link>
</Link>
{sub !== 'jobs' && (!me || me.noteJobIndicator) && (!lastCheckedJobs || lastCheckedJobs < subLatestPost?.subLatestPost) &&
{showJobIndicator &&
<span className={styles.jobIndicator}>
<span className='invisible'>{' '}</span>
</span>}

View File

@ -11,8 +11,9 @@ import { Button } from 'react-bootstrap'
import { TwitterTweetEmbed } from 'react-twitter-embed'
import YouTube from 'react-youtube'
import useDarkMode from 'use-dark-mode'
import { useState } from 'react'
import { useEffect, useState } from 'react'
import Poll from './poll'
import { commentsViewed } from '../lib/new-comments'
function BioItem ({ item, handleClick }) {
const me = useMe()
@ -99,6 +100,10 @@ function ItemText ({ item }) {
}
export default function ItemFull ({ item, bio, ...props }) {
useEffect(() => {
commentsViewed(item)
}, [item.lastCommentAt])
return (
<>
{item.parentId

View File

@ -9,6 +9,8 @@ import Pin from '../svgs/pushpin-fill.svg'
import reactStringReplace from 'react-string-replace'
import Toc from './table-of-contents'
import PollIcon from '../svgs/bar-chart-horizontal-fill.svg'
import { Badge } from 'react-bootstrap'
import { newComments } from '../lib/new-comments'
export function SearchTitle ({ title }) {
return reactStringReplace(title, /:high\[([^\]]+)\]/g, (match, i) => {
@ -34,6 +36,7 @@ export default function Item ({ item, rank, showFwdUser, toc, children }) {
useState(mine && (Date.now() < editThreshold))
const [wrap, setWrap] = useState(false)
const titleRef = useRef()
const [hasNewComments, setHasNewComments] = useState(false)
useEffect(() => {
setWrap(
@ -41,6 +44,11 @@ export default function Item ({ item, rank, showFwdUser, toc, children }) {
titleRef.current.clientHeight)
}, [])
useEffect(() => {
// if we are showing toc, then this is a full item
setHasNewComments(!toc && newComments(item))
}, [item])
return (
<>
{rank
@ -82,7 +90,10 @@ export default function Item ({ item, rank, showFwdUser, toc, children }) {
<span> \ </span>
</>}
<Link href={`/items/${item.id}`} passHref>
<a title={`${item.commentSats} sats`} className='text-reset'>{item.ncomments} comments</a>
<a title={`${item.commentSats} sats`} className='text-reset'>
{item.ncomments} comments
{hasNewComments && <>{' '}<Badge className={styles.newComment} variant={null}>new</Badge></>}
</a>
</Link>
<span> \ </span>
<span>

View File

@ -20,6 +20,11 @@ a.title:visited {
flex: 1 0 128px;
}
.newComment {
color: var(--theme-grey) !important;
background: var(--theme-clickToContextColor) !important;
}
.pin {
fill: #a5a5a5;
margin-right: .2rem;

View File

@ -8,6 +8,7 @@ import TextareaAutosize from 'react-textarea-autosize'
import { useEffect, useState } from 'react'
import Link from 'next/link'
import FeeButton from './fee-button'
import { commentsViewedAfterComment } from '../lib/new-comments'
export const CommentSchema = Yup.object({
text: Yup.string().required('required').trim()
@ -57,8 +58,10 @@ export default function Reply ({ item, onSuccess, replyOpen }) {
}
})
const ancestors = item.path.split('.')
// update all ancestors
item.path.split('.').forEach(id => {
ancestors.forEach(id => {
cache.modify({
id: `Item:${id}`,
fields: {
@ -68,6 +71,11 @@ export default function Reply ({ item, onSuccess, replyOpen }) {
}
})
})
// so that we don't see indicator for our own comments, we record this comments as the latest time
// but we also have record num comments, in case someone else commented when we did
const root = ancestors[0]
commentsViewedAfterComment(root, createComment.createdAt)
}
}
)

28
lib/new-comments.js Normal file
View File

@ -0,0 +1,28 @@
const COMMENTS_VIEW_PREFIX = 'commentsViewedAt'
const COMMENTS_NUM_PREFIX = 'commentsViewNum'
export function commentsViewed (item) {
if (!item.parentId && item.lastCommentAt) {
localStorage.setItem(`${COMMENTS_VIEW_PREFIX}:${item.id}`, new Date(item.lastCommentAt).getTime())
localStorage.setItem(`${COMMENTS_NUM_PREFIX}:${item.id}`, item.ncomments)
}
}
export function commentsViewedAfterComment (rootId, createdAt) {
localStorage.setItem(`${COMMENTS_VIEW_PREFIX}:${rootId}`, new Date(createdAt).getTime())
const existingRootComments = localStorage.getItem(`${COMMENTS_NUM_PREFIX}:${rootId}`) || 0
localStorage.setItem(`${COMMENTS_NUM_PREFIX}:${rootId}`, existingRootComments + 1)
}
export function newComments (item) {
if (!item.parentId) {
const commentsViewedAt = localStorage.getItem(`${COMMENTS_VIEW_PREFIX}:${item.id}`)
const commentsViewNum = localStorage.getItem(`${COMMENTS_NUM_PREFIX}:${item.id}`)
if (commentsViewedAt && commentsViewNum) {
return commentsViewedAt < new Date(item.lastCommentAt).getTime() || commentsViewNum < item.ncomments
}
}
return false
}