continued notification work

This commit is contained in:
keyan 2021-08-17 18:59:22 -05:00
parent c8df41bfa5
commit 0afe46c030
9 changed files with 61 additions and 47 deletions

View File

@ -5,9 +5,9 @@ export default {
Query: {
notifications: async (parent, { cursor }, { me, models }) => {
const decodedCursor = decodeCursor(cursor)
// if (!me) {
// throw new AuthenticationError('you must be logged in')
// }
if (!me) {
throw new AuthenticationError('you must be logged in')
}
/*
So that we can cursor over results, we union notifications together ...
@ -63,12 +63,15 @@ export default {
GROUP BY ${ITEM_SUBQUERY_FIELDS}, subquery.island ORDER BY max(subquery.voted_at) desc)
ORDER BY sort_time DESC
OFFSET $3
LIMIT ${LIMIT}`, 622, decodedCursor.time, decodedCursor.offset)
LIMIT ${LIMIT}`, me.id, decodedCursor.time, decodedCursor.offset)
notifications = notifications.map(n => {
n.item = { ...n }
return n
})
await models.user.update({ where: { id: me.id }, data: { checkedNotesAt: new Date() } })
return {
cursor: notifications.length === LIMIT ? nextCursorEncoded(decodedCursor) : null,
notifications

View File

@ -38,7 +38,7 @@ function Parent ({ item, rootText }) {
)
}
export default function Comment ({ item, children, replyOpen, includeParent, rootText, noComments, noReply, clickToContext }) {
export default function Comment ({ item, children, replyOpen, includeParent, rootText, noComments, noReply }) {
const [reply, setReply] = useState(replyOpen)
const [edit, setEdit] = useState()
const [collapse, setCollapse] = useState(false)
@ -50,28 +50,16 @@ export default function Comment ({ item, children, replyOpen, includeParent, roo
const [canEdit, setCanEdit] =
useState(mine && (Date.now() < editThreshold))
console.log('wtf router', router, item.id, ref.current)
useEffect(() => {
if (Number(router.query.commentId) === Number(item.id)) {
console.log(ref.current.scrollTop)
ref.current.scrollIntoView()
// ref.current.classList.add('flash-it')
ref.current.classList.add('flash-it')
}
}, [item])
return (
<div
ref={ref} onClick={() => {
if (clickToContext) {
console.log('pushing')
// router.push(`/items/${item.parentId}?commentId=${item.id}`, `/items/${item.parentId}`, { scroll: false })
router.push({
pathname: '/items/[id]',
query: { id: item.parentId, commentId: item.id }
}, `/items/${item.parentId}`)
}
}} className={includeParent ? `${clickToContext ? styles.clickToContext : ''}` : `${styles.comment} ${collapse ? styles.collapsed : ''}`}
ref={ref} className={includeParent ? '' : `${styles.comment} ${collapse ? styles.collapsed : ''}`}
>
<div className={`${itemStyles.item} ${styles.item}`}>
<UpVote itemId={item.id} meSats={item.meSats} className={styles.upvote} />

View File

@ -81,15 +81,6 @@
padding-left: .2rem;
}
.clickToContext {
border-radius: .4rem;
padding: .2rem 0;
}
.clickToContext:hover {
background-color: rgba(0, 0, 0, 0.03);
}
.comment:not(:last-child) {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
@ -99,9 +90,4 @@
padding-top: .25rem;
border-top-left-radius: 0;
border-top-right-radius: 0;
}
.clickToContext {
scroll-behavior: smooth;
cursor: pointer;
}

View File

@ -3,8 +3,11 @@ import Button from 'react-bootstrap/Button'
import { MORE_FLAT_COMMENTS } from '../fragments/comments'
import { useState } from 'react'
import Comment, { CommentSkeleton } from './comment'
import styles from './notifications.module.css'
import { useRouter } from 'next/router'
export default function CommentsFlat ({ variables, ...props }) {
const router = useRouter()
const { loading, error, data, fetchMore } = useQuery(MORE_FLAT_COMMENTS, {
variables
})
@ -12,12 +15,22 @@ export default function CommentsFlat ({ variables, ...props }) {
if (loading) {
return <CommentsFlatSkeleton />
}
const { moreFlatComments: { comments, cursor } } = data
return (
<>
{comments.map(item => (
<Comment key={item.id} item={item} {...props} />
<div
key={item.id}
className={styles.clickToContext}
onClick={() => {
router.push({
pathname: '/items/[id]',
query: { id: item.parentId, commentId: item.id }
}, `/items/${item.parentId}`)
}}
>
<Comment item={item} {...props} />
</div>
))}
<MoreFooter cursor={cursor} fetchMore={fetchMore} />
</>

View File

@ -14,7 +14,7 @@ import { useEffect } from 'react'
import { randInRange } from '../lib/rand'
function WalletSummary ({ me }) {
return `[${me.stacked},${me.sats}]`
return `${me.stacked} \\ ${me.sats}`
}
export default function Header () {
@ -32,20 +32,18 @@ export default function Header () {
if (session) {
return (
<div className='d-flex align-items-center'>
{me && me.hasNewNotes &&
<Head>
<link rel='shortcut icon' href='/favicon-notify.png' />
</Head>}
<Head>
<link rel='shortcut icon' href={me && me.hasNewNotes ? '/favicon-notify.png' : '/favicon.png'} />
</Head>
<div className='position-relative'>
<NavDropdown className='pl-0' title={`@${session.user.name}`} alignRight>
<NavDropdown className='px-0' title={`@${session.user.name}`} alignRight>
<Link href={'/' + session.user.name} passHref>
<NavDropdown.Item>profile</NavDropdown.Item>
</Link>
<Link href='/notifications' passHref>
<NavDropdown.Item onClick={() => {
// when it's a fresh click evict old notification cache
client.cache.evict({ id: 'ROOT_QUERY', fieldName: 'moreFlatComments:{}' })
client.cache.evict({ id: 'ROOT_QUERY', fieldName: 'recentlyStacked' })
client.cache.evict({ id: 'ROOT_QUERY', fieldName: 'notifications' })
}}
>
notifications

View File

@ -4,8 +4,11 @@ import { useState } from 'react'
import Comment, { CommentSkeleton } from './comment'
import Item from './item'
import { NOTIFICATIONS } from '../fragments/notifications'
import styles from './notifications.module.css'
import { useRouter } from 'next/router'
export default function Notifications ({ variables, ...props }) {
const router = useRouter()
const { loading, error, data, fetchMore } = useQuery(NOTIFICATIONS, {
variables
})
@ -14,12 +17,26 @@ export default function Notifications ({ variables, ...props }) {
return <CommentsFlatSkeleton />
}
const { notifications: { notifications, cursor } } = data
return (
<>
{/* XXX we shouldn't use the index but we don't have a unique id in this union yet */}
{notifications.map((n, i) => (
<div key={i}>
{n.__typename === 'Votification' && <small className='font-weight-bold text-success'>your {n.item.title ? 'post' : 'reply'} stacked {n.earnedSats} sats</small>}
<div
key={i}
className={styles.clickToContext}
onClick={() => {
if (n.__typename === 'Reply' || !n.item.title) {
router.push({
pathname: '/items/[id]',
query: { id: n.item.parentId, commentId: n.item.id }
}, `/items/${n.item.parentId}`)
} else {
router.push(`items/${n.item.id}`)
}
}}
>
{n.__typename === 'Votification' && <small className='font-weight-bold text-success ml-2'>your {n.item.title ? 'post' : 'reply'} stacked {n.earnedSats} sats</small>}
<div className={n.__typename === 'Votification' ? 'ml-sm-4 ml-2' : ''}>
{n.item.title
? <Item item={n.item} />

View File

@ -0,0 +1,9 @@
.clickToContext {
border-radius: .4rem;
padding: .2rem 0;
cursor: pointer;
}
.clickToContext:hover {
background-color: rgba(0, 0, 0, 0.03);
}

View File

@ -39,7 +39,7 @@ export default function UserComments ({ user }) {
<Layout noSeo>
<Seo user={user} />
<UserHeader user={user} />
<CommentsFlat variables={{ userId: user.id }} includeParent noReply clickToContext />
<CommentsFlat variables={{ userId: user.id }} includeParent noReply />
</Layout>
)
}

View File

@ -191,7 +191,7 @@ footer {
}
.flash-it {
animation: flash 2s linear 2;
animation: flash 2s linear 1;
}
@keyframes spin {