Scroll to items on push notification click (#345)

* Scroll from root item in reach on notification click

Instead of going directly to the item of the notification, we now scroll from the root item which is still in reach to the comment.

This should provide more context to the user in most cases.

* Also scroll from root item in reach in /notifications

---------

Co-authored-by: ekzyis <ek@stacker.news>
This commit is contained in:
ekzyis 2023-07-06 17:00:38 +02:00 committed by GitHub
parent 8350b1df3b
commit 37e70f9791
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 22 additions and 7 deletions

View File

@ -903,7 +903,7 @@ export default {
parents.map(({ userId }) => sendUserNotification(userId, {
title: 'you have a new reply',
body: data.text,
data: { url: `/items/${item.id}` },
item,
tag: 'REPLY'
}))
)
@ -949,7 +949,7 @@ export default {
sendUserNotification(updatedItem.userId, {
title,
body: updatedItem.title ? updatedItem.title : updatedItem.text,
data: { url: `/items/${updatedItem.id}` },
item: updatedItem,
tag: `TIP-${updatedItem.id}`
}).catch(console.error)
@ -1206,11 +1206,10 @@ export const createMentions = async (item, models) => {
update: data,
create: data
})
sendUserNotification(user.id, {
title: 'you were mentioned',
body: item.text,
data: { url: `/items/${item.id}` },
item,
tag: 'MENTION'
}).catch(console.error)
})

View File

@ -1,5 +1,6 @@
import webPush from 'web-push'
import models from '../models'
import { COMMENT_DEPTH_LIMIT } from '../../lib/constants'
webPush.setVapidDetails(
process.env.VAPID_MAILTO,
@ -31,6 +32,14 @@ const createUserFilter = (tag) => {
return key ? { user: { [key]: true } } : undefined
}
const createItemUrl = async ({ id }) => {
const [rootItem] = await models.$queryRaw(
'SELECT subpath(path, $1, 1)::text AS id FROM "Item" WHERE id = $2',
-(COMMENT_DEPTH_LIMIT + 1), Number(id)
)
return `/items/${rootItem.id}` + (rootItem.id !== id ? `?commentId=${id}` : '')
}
const sendNotification = (subscription, payload) => {
const { id, endpoint, p256dh, auth } = subscription
return webPush.sendNotification({ endpoint, keys: { p256dh, auth } }, payload)
@ -54,6 +63,11 @@ const sendNotification = (subscription, payload) => {
export async function sendUserNotification (userId, notification) {
try {
notification.data ??= {}
if (notification.item) {
notification.data.url ??= await createItemUrl(notification.item)
delete notification.item
}
const userFilter = createUserFilter(notification.tag)
const payload = createPayload(notification)
const subscriptions = await models.pushSubscription.findMany({

View File

@ -52,11 +52,13 @@ function NotificationLayout ({ children, onClick }) {
const defaultOnClick = (n, router) => () => {
if (!n.item.title) {
if (n.item.path.split('.').length > COMMENT_DEPTH_LIMIT + 1) {
const path = n.item.path.split('.')
if (path.length > COMMENT_DEPTH_LIMIT + 1) {
const rootId = path.slice(-(COMMENT_DEPTH_LIMIT + 1))[0]
router.push({
pathname: '/items/[id]',
query: { id: n.item.parentId, commentId: n.item.id }
}, `/items/${n.item.parentId}`)
query: { id: rootId, commentId: n.item.id }
}, `/items/${rootId}`)
} else {
router.push({
pathname: '/items/[id]',