Display notification when receving
This commit is contained in:
parent
5d81133b19
commit
cd87a921ea
|
@ -24,34 +24,44 @@
|
|||
},
|
||||
"notification": {
|
||||
"favourite": {
|
||||
"title": "Favourite",
|
||||
"body": "{user} favourited your post"
|
||||
},
|
||||
"reblog": {
|
||||
"title": "Boost",
|
||||
"body": "{user} boosted your post"
|
||||
},
|
||||
"quote": {
|
||||
"title": "Quote",
|
||||
"body": "{user} quoted your post"
|
||||
},
|
||||
"poll_expired": {
|
||||
"title": "Poll",
|
||||
"body": "{user} poll has ended"
|
||||
},
|
||||
"poll_vote": {
|
||||
"title": "Poll",
|
||||
"body": "{user} voted your poll"
|
||||
},
|
||||
"status": {
|
||||
"title": "Status",
|
||||
"body": "{user} just posted"
|
||||
},
|
||||
"update": {
|
||||
"title": "Update",
|
||||
"body": "{user} updated the post"
|
||||
},
|
||||
"emoji_reaction": {
|
||||
"title": "Reaction",
|
||||
"body": "{user} reacted your post"
|
||||
},
|
||||
"follow": {
|
||||
"title": "Follow",
|
||||
"body": "{user} followed you",
|
||||
"followers": "{num} followers"
|
||||
},
|
||||
"follow_request": {
|
||||
"title": "Follow Request",
|
||||
"body": "{user} requested to follow you"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,13 +21,15 @@
|
|||
"megalodon": "^9.1.1",
|
||||
"react-icons": "^4.11.0",
|
||||
"react-intl": "^6.5.1",
|
||||
"react-virtuoso": "^4.6.2"
|
||||
"react-virtuoso": "^4.6.2",
|
||||
"sanitize-html": "^2.11.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/runtime-corejs3": "^7.23.2",
|
||||
"@electron/notarize": "^2.1.0",
|
||||
"@types/node": "^18.11.18",
|
||||
"@types/react": "^18.0.26",
|
||||
"@types/sanitize-html": "^2.9.4",
|
||||
"autoprefixer": "^10.4.16",
|
||||
"electron": "^26.2.2",
|
||||
"electron-builder": "^24.6.4",
|
||||
|
|
|
@ -47,6 +47,7 @@ export default function Notifications(props: Props) {
|
|||
if (streaming.current) {
|
||||
streaming.current.removeAllListeners()
|
||||
streaming.current.stop()
|
||||
streaming.current = null
|
||||
console.log('closed notifications')
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,6 +62,7 @@ export default function Timeline(props: Props) {
|
|||
if (streaming.current) {
|
||||
streaming.current.removeAllListeners()
|
||||
streaming.current.stop()
|
||||
streaming.current = null
|
||||
console.log(`closed ${props.timeline}`)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
import { useRouter } from 'next/router'
|
||||
import Timeline from '@/components/timelines/Timeline'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { Account, db } from '@/db'
|
||||
import generator, { MegalodonInterface } from 'megalodon'
|
||||
import generator, { Entity, MegalodonInterface, WebSocketInterface } from 'megalodon'
|
||||
import Notifications from '@/components/timelines/Notifications'
|
||||
import generateNotification from '@/utils/notification'
|
||||
import { useIntl } from 'react-intl'
|
||||
|
||||
export default function Page() {
|
||||
const router = useRouter()
|
||||
const [account, setAccount] = useState<Account | null>(null)
|
||||
const [client, setClient] = useState<MegalodonInterface>(null)
|
||||
const streaming = useRef<WebSocketInterface | null>(null)
|
||||
const { formatMessage } = useIntl()
|
||||
|
||||
useEffect(() => {
|
||||
if (router.query.id) {
|
||||
|
@ -18,10 +22,33 @@ export default function Page() {
|
|||
setAccount(a)
|
||||
const c = generator(a.sns, a.url, a.access_token, 'Whalebird')
|
||||
setClient(c)
|
||||
|
||||
// Start user streaming for notification
|
||||
const instance = await c.getInstance()
|
||||
const ws = generator(a.sns, instance.data.urls.streaming_api, a.access_token, 'Whalebird')
|
||||
streaming.current = ws.userSocket()
|
||||
streaming.current.on('connect', () => {
|
||||
console.log('connect to user streaming')
|
||||
})
|
||||
streaming.current.on('notification', (notification: Entity.Notification) => {
|
||||
const [title, body] = generateNotification(notification, formatMessage)
|
||||
if (title.length > 0) {
|
||||
new window.Notification(title, { body: body })
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
f()
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (streaming.current) {
|
||||
streaming.current.removeAllListeners()
|
||||
streaming.current.stop()
|
||||
streaming.current = null
|
||||
console.log('close user streaming')
|
||||
}
|
||||
}
|
||||
}, [router.query.id])
|
||||
|
||||
if (!account || !client) return null
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
import sanitizeHtml from 'sanitize-html'
|
||||
import { Entity } from 'megalodon'
|
||||
import { MessageDescriptor } from 'react-intl'
|
||||
|
||||
const generateNotification = (
|
||||
notification: Entity.Notification,
|
||||
formatMessage: (descriptor: MessageDescriptor, values?: any, opts?: any) => string
|
||||
): [string, string] => {
|
||||
switch (notification.type) {
|
||||
case 'follow':
|
||||
return [
|
||||
formatMessage({ id: 'timeline.notification.follow.title' }),
|
||||
formatMessage({ id: 'timeline.notification.follow.body' }, { user: notification.account.acct })
|
||||
]
|
||||
case 'follow_request':
|
||||
return [
|
||||
formatMessage({ id: 'timeline.notification.follow_request.title' }),
|
||||
formatMessage({ id: 'timeline.notification.follow_requested.body' }, { user: notification.account.acct })
|
||||
]
|
||||
case 'favourite':
|
||||
return [
|
||||
formatMessage({ id: 'timeline.notification.favourite.title' }),
|
||||
formatMessage({ id: 'timeline.notification.favourite.body' }, { user: notification.account.acct })
|
||||
]
|
||||
case 'reblog':
|
||||
return [
|
||||
formatMessage({ id: 'timeline.notification.reblog.title' }),
|
||||
formatMessage({ id: 'timeline.notification.reblog.body' }, { user: notification.account.acct })
|
||||
]
|
||||
case 'poll_expired':
|
||||
return [
|
||||
formatMessage({ id: 'timeline.notification.poll_expired.title' }),
|
||||
formatMessage({ id: 'timeline.notification.poll_expired.body' }, { user: notification.account.acct })
|
||||
]
|
||||
case 'poll_vote':
|
||||
return [
|
||||
formatMessage({ id: 'timeline.notification.poll_vote.title' }),
|
||||
formatMessage({ id: 'timeline.notification.poll_vote.body' }, { user: notification.account.acct })
|
||||
]
|
||||
case 'quote':
|
||||
return [
|
||||
formatMessage({ id: 'timeline.notification.quote.title' }),
|
||||
formatMessage({ id: 'timeline.notification.quote.body' }, { user: notification.account.acct })
|
||||
]
|
||||
case 'status':
|
||||
return [
|
||||
formatMessage({ id: 'timeline.notification.status.title' }),
|
||||
formatMessage({ id: 'timeline.notification.status.body' }, { user: notification.account.acct })
|
||||
]
|
||||
case 'update':
|
||||
return [
|
||||
formatMessage({ id: 'timeline.notification.update.title' }),
|
||||
formatMessage({ id: 'timeline.notification.update.body' }, { user: notification.account.acct })
|
||||
]
|
||||
case 'emoji_reaction':
|
||||
case 'reaction':
|
||||
return [
|
||||
formatMessage({ id: 'timeline.notification.emoji_reaction.title' }),
|
||||
formatMessage({ id: 'timeline.notification.emoji_reaction.body' }, { user: notification.account.acct })
|
||||
]
|
||||
case 'mention':
|
||||
return [
|
||||
`${notification.account.acct}`,
|
||||
sanitizeHtml(notification.status!.content, {
|
||||
allowedTags: [],
|
||||
allowedAttributes: false
|
||||
})
|
||||
]
|
||||
default:
|
||||
return ['', '']
|
||||
}
|
||||
}
|
||||
|
||||
export default generateNotification
|
81
yarn.lock
81
yarn.lock
|
@ -1480,6 +1480,13 @@
|
|||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/sanitize-html@^2.9.4":
|
||||
version "2.9.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/sanitize-html/-/sanitize-html-2.9.4.tgz#bfc2df463ec35904fecc57b29ba080e53732a140"
|
||||
integrity sha512-Ym4hjmAFxF/eux7nW2yDPAj2o9RYh0vP/9V5ECoHtgJ/O9nPGslUd20CMn6WatRMlFVfjMTg3lMcWq8YyO6QnA==
|
||||
dependencies:
|
||||
htmlparser2 "^8.0.0"
|
||||
|
||||
"@types/scheduler@*":
|
||||
version "0.16.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.5.tgz#4751153abbf8d6199babb345a52e1eb4167d64af"
|
||||
|
@ -2271,6 +2278,11 @@ decompress-response@^6.0.0:
|
|||
dependencies:
|
||||
mimic-response "^3.1.0"
|
||||
|
||||
deepmerge@^4.2.2:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a"
|
||||
integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==
|
||||
|
||||
defer-to-connect@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587"
|
||||
|
@ -2355,6 +2367,36 @@ dmg-license@^1.0.11:
|
|||
smart-buffer "^4.0.2"
|
||||
verror "^1.10.0"
|
||||
|
||||
dom-serializer@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53"
|
||||
integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==
|
||||
dependencies:
|
||||
domelementtype "^2.3.0"
|
||||
domhandler "^5.0.2"
|
||||
entities "^4.2.0"
|
||||
|
||||
domelementtype@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d"
|
||||
integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==
|
||||
|
||||
domhandler@^5.0.2, domhandler@^5.0.3:
|
||||
version "5.0.3"
|
||||
resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31"
|
||||
integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==
|
||||
dependencies:
|
||||
domelementtype "^2.3.0"
|
||||
|
||||
domutils@^3.0.1:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.1.0.tgz#c47f551278d3dc4b0b1ab8cbb42d751a6f0d824e"
|
||||
integrity sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==
|
||||
dependencies:
|
||||
dom-serializer "^2.0.0"
|
||||
domelementtype "^2.3.0"
|
||||
domhandler "^5.0.3"
|
||||
|
||||
dot-prop@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-6.0.1.tgz#fc26b3cf142b9e59b74dbd39ed66ce620c681083"
|
||||
|
@ -2461,6 +2503,11 @@ enhanced-resolve@^5.15.0, enhanced-resolve@^5.7.0:
|
|||
graceful-fs "^4.2.4"
|
||||
tapable "^2.2.0"
|
||||
|
||||
entities@^4.2.0, entities@^4.4.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48"
|
||||
integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==
|
||||
|
||||
env-paths@^2.2.0, env-paths@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2"
|
||||
|
@ -2915,6 +2962,16 @@ hosted-git-info@^4.1.0:
|
|||
dependencies:
|
||||
lru-cache "^6.0.0"
|
||||
|
||||
htmlparser2@^8.0.0:
|
||||
version "8.0.2"
|
||||
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.2.tgz#f002151705b383e62433b5cf466f5b716edaec21"
|
||||
integrity sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==
|
||||
dependencies:
|
||||
domelementtype "^2.3.0"
|
||||
domhandler "^5.0.3"
|
||||
domutils "^3.0.1"
|
||||
entities "^4.4.0"
|
||||
|
||||
http-cache-semantics@^4.0.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a"
|
||||
|
@ -3048,6 +3105,11 @@ is-plain-object@^2.0.4:
|
|||
dependencies:
|
||||
isobject "^3.0.1"
|
||||
|
||||
is-plain-object@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344"
|
||||
integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==
|
||||
|
||||
is-stream@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077"
|
||||
|
@ -3563,6 +3625,11 @@ p-try@^2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
|
||||
integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
|
||||
|
||||
parse-srcset@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/parse-srcset/-/parse-srcset-1.0.2.tgz#f2bd221f6cc970a938d88556abc589caaaa2bde1"
|
||||
integrity sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==
|
||||
|
||||
path-exists@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
|
||||
|
@ -3689,7 +3756,7 @@ postcss@8.4.14:
|
|||
picocolors "^1.0.0"
|
||||
source-map-js "^1.0.2"
|
||||
|
||||
postcss@^8.4.23, postcss@^8.4.31:
|
||||
postcss@^8.3.11, postcss@^8.4.23, postcss@^8.4.31:
|
||||
version "8.4.31"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d"
|
||||
integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==
|
||||
|
@ -3954,6 +4021,18 @@ sanitize-filename@^1.6.3:
|
|||
dependencies:
|
||||
truncate-utf8-bytes "^1.0.0"
|
||||
|
||||
sanitize-html@^2.11.0:
|
||||
version "2.11.0"
|
||||
resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-2.11.0.tgz#9a6434ee8fcaeddc740d8ae7cd5dd71d3981f8f6"
|
||||
integrity sha512-BG68EDHRaGKqlsNjJ2xUB7gpInPA8gVx/mvjO743hZaeMCZ2DwzW7xvsqZ+KNU4QKwj86HJ3uu2liISf2qBBUA==
|
||||
dependencies:
|
||||
deepmerge "^4.2.2"
|
||||
escape-string-regexp "^4.0.0"
|
||||
htmlparser2 "^8.0.0"
|
||||
is-plain-object "^5.0.0"
|
||||
parse-srcset "^1.0.2"
|
||||
postcss "^8.3.11"
|
||||
|
||||
sax@^1.2.4:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/sax/-/sax-1.3.0.tgz#a5dbe77db3be05c9d1ee7785dbd3ea9de51593d0"
|
||||
|
|
Loading…
Reference in New Issue