pleroma-fe/src/stores/notifications.js
Henry Jameson afc7161b6d merge fix
2026-08-12 15:59:05 +03:00

192 lines
5.8 KiB
JavaScript

import { defineStore } from 'pinia'
import {
closeAllDesktopNotifications,
closeDesktopNotification,
} from '../services/desktop_notification_utils/desktop_notification_utils.js'
import {
isValidNotification,
maybeShowNotification,
} from '../services/notification_utils/notification_utils.js'
import { isStatusNotification } from '../services/notification_utils/notification_utils_sw.js'
import { useI18nStore } from 'src/stores/i18n.js'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useOAuthStore } from 'src/stores/oauth.js'
import { useReportsStore } from 'src/stores/reports.js'
import { useStatusesStore } from 'src/stores/statuses.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { useUsersStore } from 'src/stores/users.js'
import { dismissNotification, markNotificationsAsSeen } from 'src/api/user.js'
export const defaultState = () => ({
desktopNotificationSilence: true,
maxId: 0,
minId: Number.POSITIVE_INFINITY,
data: [],
statusNotificationRelations: new WeakMap(),
idStore: new Map(),
loading: false,
})
export const useNotificationsStore = defineStore('notifications', {
state: defaultState,
actions: {
clearNotifications() {
const blankState = defaultState()
Object.keys(defaultState()).forEach((k) => {
this[k] = blankState[k]
})
},
updateNotificationsMinMaxId(id) {
this.maxId = id > this.maxId ? id : this.maxId
this.minId = id < this.minId ? id : this.minId
},
setNotificationsLoading(value) {
this.loading = value
},
setNotificationsSilence(value) {
this.desktopNotificationSilence = value
},
updateNotification({ id, updater }) {
const notification = this.idStore.get(id)
notification && updater(notification)
},
addNewNotifications(result) {
const { timestamp, data: notifications } = result
useUsersStore().addNewUsers({
timestamp,
data: notifications.map((n) => n.from_profile),
})
notifications.forEach(
(n) => (n.from_profile = useUsersStore().findUser(n.from_profile.id)),
)
const validNotifications = notifications.filter((notification) => {
// If invalid notification, update ids but don't add it to store
if (!isValidNotification(notification)) {
console.error('Invalid notification:', notification)
this.updateNotificationsMinMaxId(notification.id)
return false
}
return true
})
useUsersStore().addNewUsers({
timestamp,
data: validNotifications.map((notification) => notification.from_profile),
})
const statusNotifications = validNotifications.filter(
(notification) =>
isStatusNotification(notification.type) && notification.status,
)
// Synchronous commit to add all the statuses
useStatusesStore().addNewStatuses({
timestamp,
statuses: statusNotifications.map(
(notification) => notification.status,
),
})
// Update references to statuses in notifications to ones in the store
statusNotifications.forEach((notification) => {
const id = notification.status.id
const referenceStatus = useStatusesStore().allStatuses.get(id)
if (referenceStatus) {
notification.status = referenceStatus
}
})
validNotifications.forEach((notification) => {
if (notification.type === 'pleroma:report') {
useReportsStore().addReport(notification.report)
}
if (notification.type === 'pleroma:emoji_reaction') {
useStatusesStore().fetchEmojiReactionsBy(notification.status.id)
}
// Only add a new notification if we don't have one for the same action
if (!this.idStore.has(notification.id)) {
this.updateNotificationsMinMaxId(notification.id)
notifications.forEach((notification) => {
this.data.push(notification)
this.idStore.set(notification.id, notification)
})
this.statusNotificationRelations.set(
notification.status,
this.idStore.get(notification.id),
)
maybeShowNotification(
useMergedConfigStore().mergedConfig.notificationVisibility,
Object.values(useSyncConfigStore().prefsStorage.simple.muteFilters),
notification,
useI18nStore().i18n,
)
} else if (notification.seen) {
this.idStore.get(notification.id).seen = true
}
})
},
notificationClicked(id) {
const notification = this.idStore.get(id)
const { type, seen } = notification
if (!seen) {
switch (type) {
case 'mention':
case 'pleroma:report':
case 'follow_request':
break
default:
this.markSingleNotificationAsSeen({ id })
}
}
},
markNotificationsAsSeen() {
this.data.forEach((notification) => {
notification.seen = true
})
markNotificationsAsSeen({
id: this.maxId,
credentials: useUsersStore().currentUser.credentials,
}).then(() => {
closeAllDesktopNotifications()
})
},
markSingleNotificationAsSeen({ id }) {
const notification = this.idStore.get(id)
if (notification) notification.seen = true
markNotificationsAsSeen({
single: true,
id,
credentials: useUsersStore().currentUser.credentials,
}).then(() => {
closeDesktopNotification(id)
})
},
dismissNotificationLocal(id) {
this.data = this.data.filter((n) => n.id !== id)
delete this.idStore.delete(id)
},
dismissNotification(id) {
this.dismissNotificationLocal(id)
dismissNotification({
id,
credentials: useOAuthStore().token,
})
},
},
})