feat: Add audio alert for incoming messages on dashboard (#1738)

Fixes: #1345
This commit is contained in:
Nithin David Thomas 2021-03-04 19:24:03 +05:30 committed by GitHub
parent ca4a766b82
commit 9e8a943ec7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 115 additions and 3 deletions

View file

@ -1,5 +1,6 @@
import AuthAPI from '../api/auth'; import AuthAPI from '../api/auth';
import BaseActionCableConnector from '../../shared/helpers/BaseActionCableConnector'; import BaseActionCableConnector from '../../shared/helpers/BaseActionCableConnector';
import { newMessageNotification } from 'shared/helpers/AudioNotificationHelper';
class ActionCableConnector extends BaseActionCableConnector { class ActionCableConnector extends BaseActionCableConnector {
constructor(app, pubsubToken) { constructor(app, pubsubToken) {
@ -63,6 +64,7 @@ class ActionCableConnector extends BaseActionCableConnector {
onLogout = () => AuthAPI.logout(); onLogout = () => AuthAPI.logout();
onMessageCreated = data => { onMessageCreated = data => {
newMessageNotification(data);
this.app.$store.dispatch('addMessage', data); this.app.$store.dispatch('addMessage', data);
}; };

View file

@ -22,6 +22,11 @@
"TITLE": "Access Token", "TITLE": "Access Token",
"NOTE": "This token can be used if you are building an API based integration" "NOTE": "This token can be used if you are building an API based integration"
}, },
"AUDIO_NOTIFICATIONS_SECTION": {
"TITLE": "Audio Notifications",
"NOTE": "Enable audio notifications in dashboard for new messages and conversations.",
"ENABLE_AUDIO": "Play audio notification when a new conversation is created or new messages arrives"
},
"EMAIL_NOTIFICATIONS_SECTION": { "EMAIL_NOTIFICATIONS_SECTION": {
"TITLE": "Email Notifications", "TITLE": "Email Notifications",
"NOTE": "Update your email notification preferences here", "NOTE": "Update your email notification preferences here",

View file

@ -1,5 +1,33 @@
<template> <template>
<div> <div>
<div class="profile--settings--row row">
<div class="columns small-3 ">
<h4 class="block-title">
{{ $t('PROFILE_SETTINGS.FORM.AUDIO_NOTIFICATIONS_SECTION.TITLE') }}
</h4>
<p>
{{ $t('PROFILE_SETTINGS.FORM.AUDIO_NOTIFICATIONS_SECTION.NOTE') }}
</p>
</div>
<div class="columns small-9">
<div>
<input
id="audio_enable_alert"
v-model="enableAudioAlerts"
class="notification--checkbox"
type="checkbox"
@input="handleAudioInput"
/>
<label for="audio_enable_alert">
{{
$t(
'PROFILE_SETTINGS.FORM.AUDIO_NOTIFICATIONS_SECTION.ENABLE_AUDIO'
)
}}
</label>
</div>
</div>
</div>
<div class="profile--settings--row row"> <div class="profile--settings--row row">
<div class="columns small-3 "> <div class="columns small-3 ">
<h4 class="block-title"> <h4 class="block-title">
@ -185,6 +213,7 @@
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import alertMixin from 'shared/mixins/alertMixin'; import alertMixin from 'shared/mixins/alertMixin';
import configMixin from 'shared/mixins/configMixin'; import configMixin from 'shared/mixins/configMixin';
import uiSettingsMixin from 'dashboard/mixins/uiSettings';
import { import {
hasPushPermissions, hasPushPermissions,
requestPushPermissions, requestPushPermissions,
@ -192,11 +221,12 @@ import {
} from '../../../../helper/pushHelper'; } from '../../../../helper/pushHelper';
export default { export default {
mixins: [alertMixin, configMixin], mixins: [alertMixin, configMixin, uiSettingsMixin],
data() { data() {
return { return {
selectedEmailFlags: [], selectedEmailFlags: [],
selectedPushFlags: [], selectedPushFlags: [],
enableAudioAlerts: false,
hasEnabledPushPermissions: false, hasEnabledPushPermissions: false,
}; };
}, },
@ -204,6 +234,7 @@ export default {
...mapGetters({ ...mapGetters({
emailFlags: 'userNotificationSettings/getSelectedEmailFlags', emailFlags: 'userNotificationSettings/getSelectedEmailFlags',
pushFlags: 'userNotificationSettings/getSelectedPushFlags', pushFlags: 'userNotificationSettings/getSelectedPushFlags',
uiSettings: 'getUISettings',
}), }),
isBrowserSafari() { isBrowserSafari() {
if (window.browserConfig) { if (window.browserConfig) {
@ -219,6 +250,10 @@ export default {
pushFlags(value) { pushFlags(value) {
this.selectedPushFlags = value; this.selectedPushFlags = value;
}, },
uiSettings(value) {
const { enable_audio_alerts: enableAudio = false } = value;
this.enableAudioAlerts = enableAudio;
},
}, },
mounted() { mounted() {
if (hasPushPermissions()) { if (hasPushPermissions()) {
@ -226,6 +261,8 @@ export default {
} }
this.$store.dispatch('userNotificationSettings/get'); this.$store.dispatch('userNotificationSettings/get');
const { enable_audio_alerts: enableAudio = false } = this.uiSettings;
this.enableAudioAlerts = enableAudio;
}, },
methods: { methods: {
onRegistrationSuccess() { onRegistrationSuccess() {
@ -277,6 +314,13 @@ export default {
this.updateNotificationSettings(); this.updateNotificationSettings();
}, },
handleAudioInput(e) {
this.enableAudioAlerts = e.target.checked;
this.updateUISettings({
enable_audio_alerts: this.enableAudioAlerts,
});
this.showAlert(this.$t('PROFILE_SETTINGS.FORM.API.UPDATE_SUCCESS'));
},
toggleInput(selected, current) { toggleInput(selected, current) {
if (selected.includes(current)) { if (selected.includes(current)) {
const newSelectedFlags = selected.filter(flag => flag !== current); const newSelectedFlags = selected.filter(flag => flag !== current);

View file

@ -20,6 +20,7 @@ import App from '../dashboard/App';
import i18n from '../dashboard/i18n'; import i18n from '../dashboard/i18n';
import createAxios from '../dashboard/helper/APIHelper'; import createAxios from '../dashboard/helper/APIHelper';
import commonHelpers from '../dashboard/helper/commons'; import commonHelpers from '../dashboard/helper/commons';
import { getAlertAudio } from '../shared/helpers/AudioNotificationHelper';
import router from '../dashboard/routes'; import router from '../dashboard/routes';
import store from '../dashboard/store'; import store from '../dashboard/store';
import vueActionCable from '../dashboard/helper/actionCable'; import vueActionCable from '../dashboard/helper/actionCable';
@ -70,7 +71,6 @@ window.onload = () => {
}).$mount('#app'); }).$mount('#app');
vueActionCable.init(); vueActionCable.init();
}; };
window.addEventListener('load', () => { window.addEventListener('load', () => {
verifyServiceWorkerExistence(registration => verifyServiceWorkerExistence(registration =>
registration.pushManager.getSubscription().then(subscription => { registration.pushManager.getSubscription().then(subscription => {
@ -79,4 +79,5 @@ window.addEventListener('load', () => {
} }
}) })
); );
getAlertAudio();
}); });

View file

@ -1,9 +1,69 @@
import { MESSAGE_TYPE } from 'shared/constants/messages';
const notificationAudio = require('shared/assets/audio/ding.mp3'); const notificationAudio = require('shared/assets/audio/ding.mp3');
import axios from 'axios';
export const playNotificationAudio = () => { export const playNotificationAudio = () => {
try { try {
new Audio(notificationAudio).play(); new Audio(notificationAudio).play();
} catch (error) { } catch (error) {
console.log(error); // error
} }
}; };
export const getAlertAudio = async () => {
window.playAudioAlert = () => {};
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
const playsound = audioBuffer => {
window.playAudioAlert = () => {
const source = audioCtx.createBufferSource();
source.buffer = audioBuffer;
source.connect(audioCtx.destination);
source.loop = false;
source.start();
};
};
try {
const response = await axios.get('/dashboard/audios/ding.mp3', {
responseType: 'arraybuffer',
});
audioCtx.decodeAudioData(response.data).then(playsound);
} catch (error) {
// error
}
};
const shouldPlayAudio = data => {
const { conversation_id: currentConvId } = window.WOOT.$route.params;
const currentUserId = window.WOOT.$store.getters.getCurrentUserID;
const {
conversation_id: incomingConvId,
sender_id: senderId,
message_type: messageType,
} = data;
const isFromCurrentUser = currentUserId === senderId;
const playAudio =
currentConvId !== incomingConvId &&
!isFromCurrentUser &&
messageType === MESSAGE_TYPE.INCOMING;
return playAudio;
};
export const newMessageNotification = data => {
const {
enable_audio_alerts: enableAudioAlerts = false,
} = window.WOOT.$store.getters.getUISettings;
if (!enableAudioAlerts) return false;
if (document.hidden) {
window.playAudioAlert();
} else {
const playAudio = shouldPlayAudio(data);
if (playAudio) {
window.playAudioAlert();
}
}
return false;
};

Binary file not shown.