diff --git a/api/resolvers/notifications.js b/api/resolvers/notifications.js
index 9d7f2d42..59b752fb 100644
--- a/api/resolvers/notifications.js
+++ b/api/resolvers/notifications.js
@@ -43,14 +43,14 @@ export default {
*/
let notifications = await models.$queryRaw(`
- SELECT ${ITEM_FIELDS}, "Item".created_at as sort_time, NULL as "earnedSats",
+ SELECT ${ITEM_FIELDS}, "Item".created_at as "sortTime", NULL as "earnedSats",
false as mention
From "Item"
JOIN "Item" p ON "Item"."parentId" = p.id
WHERE p."userId" = $1
AND "Item"."userId" <> $1 AND "Item".created_at <= $2
UNION ALL
- (SELECT ${ITEM_SUBQUERY_FIELDS}, max(subquery.voted_at) as sort_time,
+ (SELECT ${ITEM_SUBQUERY_FIELDS}, max(subquery.voted_at) as "sortTime",
sum(subquery.sats) as "earnedSats", false as mention
FROM
(SELECT ${ITEM_FIELDS}, "Vote".created_at as voted_at, "Vote".sats,
@@ -64,7 +64,7 @@ export default {
AND "Item"."userId" = $1) subquery
GROUP BY ${ITEM_SUBQUERY_FIELDS}, subquery.island ORDER BY max(subquery.voted_at) desc)
UNION ALL
- (SELECT ${ITEM_FIELDS}, "Mention".created_at as sort_time, NULL as "earnedSats",
+ (SELECT ${ITEM_FIELDS}, "Mention".created_at as "sortTime", NULL as "earnedSats",
true as mention
FROM "Mention"
JOIN "Item" on "Mention"."itemId" = "Item".id
@@ -73,7 +73,7 @@ export default {
AND "Mention".created_at <= $2
AND "Item"."userId" <> $1
AND p."userId" <> $1)
- ORDER BY sort_time DESC
+ ORDER BY "sortTime" DESC
OFFSET $3
LIMIT ${LIMIT}`, me.id, decodedCursor.time, decodedCursor.offset)
@@ -82,9 +82,11 @@ export default {
return n
})
+ const { checkedNotesAt } = await models.user.findUnique({ where: { id: me.id } })
await models.user.update({ where: { id: me.id }, data: { checkedNotesAt: new Date() } })
return {
+ lastChecked: checkedNotesAt,
cursor: notifications.length === LIMIT ? nextCursorEncoded(decodedCursor) : null,
notifications
}
diff --git a/api/typeDefs/notifications.js b/api/typeDefs/notifications.js
index 47c4f369..3071db4e 100644
--- a/api/typeDefs/notifications.js
+++ b/api/typeDefs/notifications.js
@@ -8,20 +8,24 @@ export default gql`
type Votification {
earnedSats: Int!
item: Item!
+ sortTime: String!
}
type Reply {
item: Item!
+ sortTime: String!
}
type Mention {
mention: Boolean!
item: Item!
+ sortTime: String!
}
union Notification = Reply | Votification | Mention
type Notifications {
+ lastChecked: String
cursor: String
notifications: [Notification!]!
}
diff --git a/components/notifications.js b/components/notifications.js
index 8bf60f15..0632d519 100644
--- a/components/notifications.js
+++ b/components/notifications.js
@@ -7,9 +7,47 @@ import { NOTIFICATIONS } from '../fragments/notifications'
import styles from './notifications.module.css'
import { useRouter } from 'next/router'
-export default function Notifications ({ variables, ...props }) {
+function Notification ({ key, n }) {
const router = useRouter()
const client = useApolloClient()
+ return (
+
{
+ if (n.__typename === 'Reply' || !n.item.title) {
+ // evict item from cache so that it has current state
+ // e.g. if they previously visited before a recent comment
+ client.cache.evict({ id: `Item:${n.item.parentId}` })
+ router.push({
+ pathname: '/items/[id]',
+ query: { id: n.item.parentId, commentId: n.item.id }
+ }, `/items/${n.item.parentId}`)
+ } else {
+ client.cache.evict({ id: `Item:${n.item.id}` })
+ router.push(`items/${n.item.id}`)
+ }
+ }}
+ >
+ {n.__typename === 'Votification' &&
+
your {n.item.title ? 'post' : 'reply'} stacked {n.earnedSats} sats}
+ {n.__typename === 'Mention' &&
+
you were mentioned in}
+
+ {n.item.title
+ ?
+ : }
+
+
+ )
+}
+
+export default function Notifications ({ variables }) {
const { loading, error, data, fetchMore } = useQuery(NOTIFICATIONS, {
variables
})
@@ -17,45 +55,26 @@ export default function Notifications ({ variables, ...props }) {
if (loading) {
return
}
- const { notifications: { notifications, cursor } } = data
+
+ const { notifications: { notifications, cursor, lastChecked } } = data
+
+ const [fresh, old] =
+ notifications.reduce((result, n) => {
+ result[new Date(n.sortTime).getTime() > lastChecked ? 0 : 1].push(n)
+ return result
+ },
+ [[], []])
return (
<>
{/* XXX we shouldn't use the index but we don't have a unique id in this union yet */}
- {notifications.map((n, i) => (
- {
- if (n.__typename === 'Reply' || !n.item.title) {
- // evict item from cache so that it has current state
- // e.g. if they previously visited before a recent comment
- client.cache.evict({ id: `Item:${n.item.parentId}` })
- router.push({
- pathname: '/items/[id]',
- query: { id: n.item.parentId, commentId: n.item.id }
- }, `/items/${n.item.parentId}`)
- } else {
- client.cache.evict({ id: `Item:${n.item.id}` })
- router.push(`items/${n.item.id}`)
- }
- }}
- >
- {n.__typename === 'Votification' &&
-
your {n.item.title ? 'post' : 'reply'} stacked {n.earnedSats} sats}
- {n.__typename === 'Mention' &&
-
you were mentioned in}
-
- {n.item.title
- ?
- : }
-
-
+
+ {fresh.map((n, i) => (
+
+ ))}
+
+ {old.map((n, i) => (
+
))}
>
diff --git a/components/notifications.module.css b/components/notifications.module.css
index c6ee5b81..343e1ca0 100644
--- a/components/notifications.module.css
+++ b/components/notifications.module.css
@@ -6,4 +6,9 @@
.clickToContext:hover {
background-color: rgba(0, 0, 0, 0.03);
+}
+
+.fresh {
+ background-color: rgba(0, 0, 0, 0.03);
+ border-radius: .4rem;
}
\ No newline at end of file
diff --git a/fragments/notifications.js b/fragments/notifications.js
index 0cb531a2..f855e30f 100644
--- a/fragments/notifications.js
+++ b/fragments/notifications.js
@@ -7,9 +7,11 @@ export const NOTIFICATIONS = gql`
query Notifications($cursor: String) {
notifications(cursor: $cursor) {
cursor
+ lastChecked
notifications {
__typename
... on Mention {
+ sortTime
mention
item {
...ItemFields
@@ -17,6 +19,7 @@ export const NOTIFICATIONS = gql`
}
}
... on Votification {
+ sortTime
earnedSats
item {
...ItemFields
@@ -24,6 +27,7 @@ export const NOTIFICATIONS = gql`
}
}
... on Reply {
+ sortTime
item {
...ItemFields
text
diff --git a/pages/_app.js b/pages/_app.js
index 51b0dc52..95895291 100644
--- a/pages/_app.js
+++ b/pages/_app.js
@@ -55,17 +55,13 @@ const client = new ApolloClient({
const notifications = existing ? existing.notifications : []
return {
cursor: incoming.cursor,
- notifications: [...notifications, ...incoming.notifications]
+ notifications: [...notifications, ...incoming.notifications],
+ lastChecked: incoming.lastChecked
}
},
read (existing) {
- if (existing) {
- return {
- cursor: existing.cursor,
- notifications: existing.notifications
- }
- }
+ return existing
}
}
}