forked from BRETT/BRETT
Initial Commit
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
import { toast } from 'vue-sonner'
|
||||
import type { ReactionEventPayload } from '@/composables/useCommentReactions'
|
||||
import type { UploadReactionEventPayload } from '@/composables/useUploadReactions'
|
||||
import type { LiveComment } from '@/composables/useLiveComments'
|
||||
import type { AppNotification } from '@/composables/useNotifications'
|
||||
|
||||
export default defineNuxtPlugin(() => {
|
||||
const { user } = useAuth()
|
||||
const { fetchAll, addLive, reset } = useNotifications()
|
||||
const { pushLive } = useLiveComments()
|
||||
const motd = useMotd()
|
||||
const { applyEvent } = useCommentReactions()
|
||||
const { applyEvent: applyUploadEvent } = useUploadReactions()
|
||||
|
||||
let ws: WebSocket | null = null
|
||||
let reconnectTimer: ReturnType<typeof setTimeout> | undefined
|
||||
|
||||
function connect() {
|
||||
if (ws) return
|
||||
const protocol = location.protocol === 'https:' ? 'wss' : 'ws'
|
||||
const socket = new WebSocket(`${protocol}://${location.host}/_ws`)
|
||||
ws = socket
|
||||
|
||||
socket.onmessage = (event) => {
|
||||
try {
|
||||
const message = JSON.parse(event.data as string)
|
||||
if (message.type === 'comment') {
|
||||
pushLive(message.comment as LiveComment)
|
||||
}
|
||||
else if (message.type === 'reaction') {
|
||||
applyEvent(message as ReactionEventPayload)
|
||||
}
|
||||
else if (message.type === 'upload-reaction') {
|
||||
applyUploadEvent(message as UploadReactionEventPayload)
|
||||
}
|
||||
else if (message.type === 'motd') {
|
||||
motd.value = typeof message.message === 'string' ? message.message : ''
|
||||
}
|
||||
else if (message.type === 'notification') {
|
||||
const n = message.notification as AppNotification
|
||||
addLive(n, typeof message.unreadCount === 'number' ? message.unreadCount : undefined)
|
||||
toast(n.isMention ? `${n.actorName} hat dich erwähnt` : `${n.actorName} hat in einem abonnierten Thread kommentiert`, {
|
||||
id: `notification-${n.uploadId}`,
|
||||
description: n.content?.slice(0, 80) || undefined,
|
||||
action: {
|
||||
label: 'Ansehen',
|
||||
onClick: () => navigateTo(`/thread/${n.uploadId}#comment-${n.commentId}`),
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
catch {
|
||||
// ungültige Nachricht ignorieren
|
||||
}
|
||||
}
|
||||
|
||||
socket.onclose = () => {
|
||||
if (ws === socket) ws = null
|
||||
reconnectTimer = setTimeout(connect, 3000)
|
||||
}
|
||||
|
||||
socket.onerror = () => {
|
||||
socket.close()
|
||||
}
|
||||
}
|
||||
|
||||
function disconnect() {
|
||||
clearTimeout(reconnectTimer)
|
||||
ws?.close()
|
||||
ws = null
|
||||
}
|
||||
|
||||
// Bei Login/Logout neu verbinden, damit die Server-seitige User-Zuordnung stimmt
|
||||
watch(() => user.value?.id, (id) => {
|
||||
disconnect()
|
||||
connect()
|
||||
if (id) {
|
||||
fetchAll().catch(() => {})
|
||||
}
|
||||
else {
|
||||
reset()
|
||||
}
|
||||
}, { immediate: true })
|
||||
})
|
||||
Reference in New Issue
Block a user