import apiService from '../services/api/api.service.js' import { isStatusNotification, isValidNotification, maybeShowNotification } from '../services/notification_utils/notification_utils.js' import { closeDesktopNotification, closeAllDesktopNotifications } from '../services/desktop_notification_utils/desktop_notification_utils.js' const emptyNotifications = () => ({ desktopNotificationSilence: true, maxId: 0, minId: Number.POSITIVE_INFINITY, data: [], idStore: {}, loading: false }) export const defaultState = () => ({ ...emptyNotifications() }) export const notifications = { state: defaultState(), mutations: { addNewNotifications (state, { notifications }) { notifications.forEach(notification => { state.data.push(notification) state.idStore[notification.id] = notification }) }, clearNotifications (state) { state = emptyNotifications() }, updateNotificationsMinMaxId (state, id) { state.maxId = id > state.maxId ? id : state.maxId state.minId = id < state.minId ? id : state.minId }, setNotificationsLoading (state, { value }) { state.loading = value }, setNotificationsSilence (state, { value }) { state.desktopNotificationSilence = value }, markNotificationsAsSeen (state) { state.data.forEach((notification) => { notification.seen = true }) }, markSingleNotificationAsSeen (state, { id }) { const notification = state.idStore[id] if (notification) notification.seen = true }, dismissNotification (state, { id }) { state.data = state.data.filter(n => n.id !== id) delete state.idStore[id] }, updateNotification (state, { id, updater }) { const notification = state.idStore[id] notification && updater(notification) } }, actions: { addNewNotifications (store, { notifications, older }) { const { commit, dispatch, state, rootState } = store 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) commit('updateNotificationsMinMaxId', notification.id) return false } return true }) const statusNotifications = validNotifications.filter(notification => isStatusNotification(notification.type) && notification.status) // Synchronous commit to add all the statuses commit('addNewStatuses', { 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 = rootState.statuses.allStatusesObject[id] if (referenceStatus) { notification.status = referenceStatus } }) validNotifications.forEach(notification => { if (notification.type === 'pleroma:report') { dispatch('addReport', notification.report) } if (notification.type === 'pleroma:emoji_reaction') { dispatch('fetchEmojiReactionsBy', notification.status.id) } // Only add a new notification if we don't have one for the same action // eslint-disable-next-line no-prototype-builtins if (!state.idStore.hasOwnProperty(notification.id)) { commit('updateNotificationsMinMaxId', notification.id) commit('addNewNotifications', { notifications: [notification] }) maybeShowNotification(store, notification) } else if (notification.seen) { state.idStore[notification.id].seen = true } }) }, notificationClicked ({ state, dispatch }, { id }) { const notification = state.idStore[id] const { type, seen } = notification if (!seen) { switch (type) { case 'mention': case 'pleroma:report': case 'follow_request': break default: dispatch('markSingleNotificationAsSeen', { id }) } } }, setNotificationsLoading ({ rootState, commit }, { value }) { commit('setNotificationsLoading', { value }) }, setNotificationsSilence ({ rootState, commit }, { value }) { commit('setNotificationsSilence', { value }) }, markNotificationsAsSeen ({ rootState, state, commit }) { commit('markNotificationsAsSeen') apiService.markNotificationsAsSeen({ id: state.maxId, credentials: rootState.users.currentUser.credentials }).then(() => { closeAllDesktopNotifications(rootState) }) }, markSingleNotificationAsSeen ({ rootState, commit }, { id }) { commit('markSingleNotificationAsSeen', { id }) apiService.markNotificationsAsSeen({ single: true, id, credentials: rootState.users.currentUser.credentials }).then(() => { closeDesktopNotification(rootState, { id }) }) }, dismissNotificationLocal ({ rootState, commit }, { id }) { commit('dismissNotification', { id }) }, dismissNotification ({ rootState, commit }, { id }) { commit('dismissNotification', { id }) rootState.api.backendInteractor.dismissNotification({ id }) }, updateNotification ({ rootState, commit }, { id, updater }) { commit('updateNotification', { id, updater }) } } } export default notifications