logo

pleroma-fe

My custom branche(s) on git.pleroma.social/pleroma/pleroma-fe git clone https://hacktivis.me/git/pleroma-fe.git
commit: ec2937ec1f3b0ae153f79604eb35b57ffe0f9af2
parent c059f4a7ee16c0128c348c43c9d468e7cfdb5ef7
Author: Henry Jameson <me@hjkos.com>
Date:   Mon, 13 Nov 2023 17:29:25 +0200

add options for marking single notification as read

Diffstat:

Msrc/components/notification/notification.js6++++++
Msrc/components/notification/notification.vue1+
Msrc/components/notifications/notifications.js20++++++++++++++++++++
Msrc/components/notifications/notifications.vue6+++++-
Msrc/components/status/status.js3+++
Msrc/components/status/status.vue3+++
Msrc/modules/statuses.js8++++++++
Msrc/services/desktop_notification_utils/desktop_notification_utils.js22+++++++++++++++++++++-
Msrc/services/notification_utils/notification_utils.js5+++--
Msrc/services/sw/sw.js9+++++++++
Msrc/sw.js6++++++
11 files changed, 85 insertions(+), 4 deletions(-)

diff --git a/src/components/notification/notification.js b/src/components/notification/notification.js @@ -50,6 +50,7 @@ const Notification = { } }, props: ['notification'], + emits: ['interacted'], components: { StatusContent, UserAvatar, @@ -72,6 +73,9 @@ const Notification = { getUser (notification) { return this.$store.state.users.usersObject[notification.from_profile.id] }, + interacted () { + this.$emit('interacted') + }, toggleMute () { this.unmuted = !this.unmuted }, @@ -95,6 +99,7 @@ const Notification = { } }, doApprove () { + this.$emit('interacted') this.$store.state.api.backendInteractor.approveUser({ id: this.user.id }) this.$store.dispatch('removeFollowRequest', this.user) this.$store.dispatch('markSingleNotificationAsSeen', { id: this.notification.id }) @@ -114,6 +119,7 @@ const Notification = { } }, doDeny () { + this.$emit('interacted') this.$store.state.api.backendInteractor.denyUser({ id: this.user.id }) .then(() => { this.$store.dispatch('dismissNotificationLocal', { id: this.notification.id }) diff --git a/src/components/notification/notification.vue b/src/components/notification/notification.vue @@ -6,6 +6,7 @@ class="Notification" :compact="true" :statusoid="notification.status" + @interacted="interacted" /> </article> <article v-else> diff --git a/src/components/notifications/notifications.js b/src/components/notifications/notifications.js @@ -159,6 +159,26 @@ const Notifications = { updateScrollPosition () { this.showScrollTop = this.$refs.root.offsetTop < this.scrollerRef.scrollTop }, + notificationClicked (notification) { + const { type, id, seen } = notification + if (!seen) { + switch (type) { + case 'mention': + case 'pleroma:report': + case 'follow_request': + break + default: + this.markOneAsSeen(id) + } + } + }, + notificationInteracted (notification) { + const { id, seen } = notification + if (!seen) this.markOneAsSeen(id) + }, + markOneAsSeen (id) { + this.$store.dispatch('markSingleNotificationAsSeen', { id }) + }, markAsSeen () { this.$store.dispatch('markNotificationsAsSeen') this.seenToDisplayCount = DEFAULT_SEEN_TO_DISPLAY_COUNT diff --git a/src/components/notifications/notifications.vue b/src/components/notifications/notifications.vue @@ -67,9 +67,13 @@ role="listitem" class="notification" :class="{unseen: !minimalMode && !notification.seen}" + @click="e => notificationClicked(notification)" > <div class="notification-overlay" /> - <notification :notification="notification" /> + <notification + :notification="notification" + @interacted="e => notificationInteracted(notification)" + /> </div> </div> <div class="panel-footer"> diff --git a/src/components/status/status.js b/src/components/status/status.js @@ -154,6 +154,7 @@ const Status = { 'controlledSetMediaPlaying', 'dive' ], + emits: ['interacted'], data () { return { uncontrolledReplying: false, @@ -442,9 +443,11 @@ const Status = { this.error = error }, clearError () { + this.$emit('interacted') this.error = undefined }, toggleReplying () { + this.$emit('interacted') controlledOrUncontrolledToggle(this, 'replying') }, gotoOriginal (id) { diff --git a/src/components/status/status.vue b/src/components/status/status.vue @@ -508,14 +508,17 @@ :visibility="status.visibility" :logged-in="loggedIn" :status="status" + @click="$emit('interacted')" /> <favorite-button :logged-in="loggedIn" :status="status" + @click="$emit('interacted')" /> <ReactButton v-if="loggedIn" :status="status" + @click="$emit('interacted')" /> <extra-buttons :status="status" diff --git a/src/modules/statuses.js b/src/modules/statuses.js @@ -17,6 +17,10 @@ import { isValidNotification, maybeShowNotification } from '../services/notification_utils/notification_utils.js' +import { + closeDesktopNotification, + closeAllDesktopNotifications +} from '../services/desktop_notification_utils/desktop_notification_utils.js' import apiService from '../services/api/api.service.js' const emptyTl = (userId = 0) => ({ @@ -726,6 +730,8 @@ const statuses = { apiService.markNotificationsAsSeen({ id: rootState.statuses.notifications.maxId, credentials: rootState.users.currentUser.credentials + }).then(() => { + closeAllDesktopNotifications(rootState) }) }, markSingleNotificationAsSeen ({ rootState, commit }, { id }) { @@ -734,6 +740,8 @@ const statuses = { single: true, id, credentials: rootState.users.currentUser.credentials + }).then(() => { + closeDesktopNotification(rootState, id) }) }, dismissNotificationLocal ({ rootState, commit }, { id }) { diff --git a/src/services/desktop_notification_utils/desktop_notification_utils.js b/src/services/desktop_notification_utils/desktop_notification_utils.js @@ -1,4 +1,8 @@ -import { showDesktopNotification as swDesktopNotification, isSWSupported } from '../sw/sw.js' +import { + showDesktopNotification as swDesktopNotification, + closeDesktopNotification as swCloseDesktopNotification, + isSWSupported +} from '../sw/sw.js' const state = { failCreateNotif: false } export const showDesktopNotification = (rootState, desktopNotificationOpts) => { @@ -16,3 +20,19 @@ export const showDesktopNotification = (rootState, desktopNotificationOpts) => { } } } + +export const closeDesktopNotification = (rootState, id) => { + if (!('Notification' in window && window.Notification.permission === 'granted')) return + + if (isSWSupported()) { + swCloseDesktopNotification({ id }) + } +} + +export const closeAllDesktopNotifications = (rootState) => { + if (!('Notification' in window && window.Notification.permission === 'granted')) return + + if (isSWSupported()) { + swCloseDesktopNotification() + } +} diff --git a/src/services/notification_utils/notification_utils.js b/src/services/notification_utils/notification_utils.js @@ -1,6 +1,7 @@ import { filter, sortBy, includes } from 'lodash' import { muteWordHits } from '../status_parser/status_parser.js' import { showDesktopNotification } from '../desktop_notification_utils/desktop_notification_utils.js' + import FaviconService from 'src/services/favicon_service/favicon_service.js' let cachedBadgeUrl = null @@ -68,8 +69,8 @@ export const maybeShowNotification = (store, notification) => { export const filteredNotificationsFromStore = (store, types) => { // map is just to clone the array since sort mutates it and it causes some issues - let sortedNotifications = notificationsFromStore(store).map(_ => _).sort(sortById) - sortedNotifications = sortBy(sortedNotifications, 'seen') + const sortedNotifications = notificationsFromStore(store).map(_ => _).sort(sortById) + // TODO implement sorting elsewhere and make it optional return sortedNotifications.filter( (notification) => (types || visibleTypes(store)).includes(notification.type) ) diff --git a/src/services/sw/sw.js b/src/services/sw/sw.js @@ -96,6 +96,15 @@ export async function showDesktopNotification (content) { sw.postMessage({ type: 'desktopNotification', content }) } +export async function closeDesktopNotification ({ id }) { + const { active: sw } = await window.navigator.serviceWorker.getRegistration() + if (id >= 0) { + sw.postMessage({ type: 'desktopNotificationClose', content: { id } }) + } else { + sw.postMessage({ type: 'desktopNotificationClose', content: { all: true } }) + } +} + export async function updateFocus () { const { active: sw } = await window.navigator.serviceWorker.getRegistration() sw.postMessage({ type: 'updateFocus' }) diff --git a/src/sw.js b/src/sw.js @@ -66,6 +66,12 @@ self.addEventListener('message', async (event) => { self.registration.showNotification(title, rest) } + if (type === 'desktopNotificationClose') { + const { id, all } = content + const search = all ? null : { tag: id } + self.registration.getNotifications(search).forEach(n => n.close()) + } + if (type === 'updateFocus') { state.lastFocused = event.source.id