Skip to content

Commit

Permalink
Merge pull request #1952 from nextcloud/backport/1947/stable27
Browse files Browse the repository at this point in the history
[stable27] fix: separate creation of browser notifications and sounds from Vue rendering
  • Loading branch information
AndyScherzinger authored Jun 13, 2024
2 parents 1612fcb + 3460562 commit 962d491
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 91 deletions.
4 changes: 2 additions & 2 deletions js/notifications-main.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/notifications-main.js.map

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

85 changes: 1 addition & 84 deletions src/Components/Notification.vue
Original file line number Diff line number Diff line change
Expand Up @@ -82,16 +82,13 @@ import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
import Close from 'vue-material-design-icons/Close.vue'
import Message from 'vue-material-design-icons/Message.vue'
import { showError } from '@nextcloud/dialogs'
import { loadState } from '@nextcloud/initial-state'
import { Howl } from 'howler'
import Action from './Action.vue'
import { generateOcsUrl, generateFilePath } from '@nextcloud/router'
import { generateOcsUrl } from '@nextcloud/router'
import moment from '@nextcloud/moment'
import RichText from '@nextcloud/vue-richtext'
import DefaultParameter from './Parameters/DefaultParameter.vue'
import File from './Parameters/File.vue'
import User from './Parameters/User.vue'
import { emit } from '@nextcloud/event-bus'
export default {
name: 'Notification',
Expand Down Expand Up @@ -247,49 +244,6 @@ export default {
mounted() {
this._$el = $(this.$el)
// Parents: TransitionGroup > Transition > HeaderMenu
if (typeof this.$parent.$parent.$parent.showBrowserNotifications === 'undefined') {
console.error('Failed to read showBrowserNotifications property from App component')
}
if (this.$parent.$parent.$parent.backgroundFetching) {
// Can not rely on showBrowserNotifications because each tab should
// be able to utilize the data from the notification in events.
const event = {
notification: this.$props,
}
emit('notifications:notification:received', event)
}
if (this.shouldNotify
&& this.$parent.$parent.$parent.showBrowserNotifications
&& this.$parent.$parent.$parent.webNotificationsThresholdId < this.notificationId) {
this._createWebNotification()
if (this.app === 'spreed' && this.objectType === 'call') {
if (loadState('notifications', 'sound_talk')) {
const sound = new Howl({
src: [
generateFilePath('notifications', 'img', 'talk.ogg'),
],
volume: 0.5,
})
sound.play()
}
} else if (loadState('notifications', 'sound_notification')) {
const sound = new Howl({
src: [
generateFilePath('notifications', 'img', 'notification.ogg'),
],
volume: 0.5,
})
sound.play()
}
}
},
methods: {
Expand Down Expand Up @@ -337,43 +291,6 @@ export default {
showError(t('notifications', 'Failed to dismiss notification'))
})
},
/**
* Create a browser notification
*
* @see https://developer.mozilla.org/en/docs/Web/API/notification
*/
_createWebNotification() {
const n = new Notification(this.subject, {
title: this.subject,
lang: OC.getLocale(),
body: this.message,
icon: this.icon,
tag: this.notificationId,
})
if (this.link) {
n.onclick = async function(e) {
const event = {
cancelAction: false,
notification: this.$props,
action: {
url: this.link,
type: 'WEB',
},
}
await emit('notifications:action:execute', event)
if (!event.cancelAction) {
console.debug('Redirecting because of a click onto a notification', this.link)
window.location.href = this.link
}
// Best effort try to bring the tab to the foreground (works at least in Chrome, not in Firefox)
window.focus()
}.bind(this)
}
},
},
}
</script>
Expand Down
19 changes: 18 additions & 1 deletion src/NotificationsApp.vue
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
import Close from 'vue-material-design-icons/Close.vue'
import axios from '@nextcloud/axios'
import { getCurrentUser } from '@nextcloud/auth'
import { subscribe, unsubscribe } from '@nextcloud/event-bus'
import { emit, subscribe, unsubscribe } from '@nextcloud/event-bus'
import { showError } from '@nextcloud/dialogs'
import { loadState } from '@nextcloud/initial-state'
import {
Expand All @@ -113,6 +113,7 @@ import Message from 'vue-material-design-icons/Message.vue'
import NcEmptyContent from '@nextcloud/vue/dist/Components/NcEmptyContent.js'
import { getCapabilities } from '@nextcloud/capabilities'
import NcHeaderMenu from '@nextcloud/vue/dist/Components/NcHeaderMenu.js'
import { createWebNotification } from './services/webNotificationsService.js'
export default {
name: 'NotificationsApp',
Expand Down Expand Up @@ -394,6 +395,7 @@ export default {
this.lastETag = response.headers.etag
this.lastTabId = response.tabId
this.notifications = response.data
this.processWebNotifications(response.data)
console.debug('Got notification data, restoring default polling interval.')
this._setPollingInterval(this.pollIntervalBase)
this._updateDocTitleOnNewNotifications(this.notifications)
Expand Down Expand Up @@ -510,6 +512,21 @@ export default {
this.webNotificationsGranted = permissions === 'granted'
})
},
processWebNotifications(notifications) {
notifications.forEach(notification => {
if (this.backgroundFetching) {
// Can not rely on showBrowserNotifications because each tab should
// be able to utilize the data from the notification in events.
const event = { notification }
emit('notifications:notification:received', event)
}
if (this.showBrowserNotifications && this.webNotificationsThresholdId < notification.notificationId) {
createWebNotification(notification)
}
})
},
},
}
</script>
Expand Down
85 changes: 85 additions & 0 deletions src/services/webNotificationsService.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

import { emit } from '@nextcloud/event-bus'
import { loadState } from '@nextcloud/initial-state'
import { generateFilePath } from '@nextcloud/router'
import { Howl } from 'howler'

/**
* Create a browser notification
*
* @param {object} notification notification object
* @see https://developer.mozilla.org/en/docs/Web/API/notification
*/
const createWebNotification = (notification) => {
if (!notification.shouldNotify) {
return
}

const n = new Notification(notification.subject, {
title: notification.subject,
lang: OC.getLocale(),
body: notification.message,
icon: notification.icon,
tag: notification.notificationId,
})

if (notification.link) {
n.onclick = async function(e) {
const event = {
cancelAction: false,
notification,
action: {
url: notification.link,
type: 'WEB',
},
}
await emit('notifications:action:execute', event)

if (!event.cancelAction) {
console.debug('Redirecting because of a click onto a notification', notification.link)
window.location.href = notification.link
}

// Best effort try to bring the tab to the foreground (works at least in Chrome, not in Firefox)
window.focus()
}
}

playNotificationSound(notification)
}

/**
* Play a notification sound (if enabled on instance)
* @param {object} notification notification object
*/
const playNotificationSound = (notification) => {
if (notification.app === 'spreed' && notification.objectType === 'call') {
if (loadState('notifications', 'sound_talk')) {
const sound = new Howl({
src: [
generateFilePath('notifications', 'img', 'talk.ogg'),
],
volume: 0.5,
})

sound.play()
}
} else if (loadState('notifications', 'sound_notification')) {
const sound = new Howl({
src: [
generateFilePath('notifications', 'img', 'notification.ogg'),
],
volume: 0.5,
})

sound.play()
}
}

export {
createWebNotification,
}

0 comments on commit 962d491

Please sign in to comment.