mirror of
				https://github.com/lingble/chatwoot.git
				synced 2025-10-30 18:47:51 +00:00 
			
		
		
		
	feat: Add new audio alert options (#6141)
Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
This commit is contained in:
		 Sivin Varghese
					Sivin Varghese
				
			
				
					committed by
					
						 Pranav Raj S
						Pranav Raj S
					
				
			
			
				
	
			
			
			 Pranav Raj S
						Pranav Raj S
					
				
			
						parent
						
							10a03cae24
						
					
				
				
					commit
					02a687b226
				
			| @@ -58,10 +58,20 @@ | ||||
|       "AUDIO_NOTIFICATIONS_SECTION": { | ||||
|         "TITLE": "Audio Notifications", | ||||
|         "NOTE": "Enable audio notifications in dashboard for new messages and conversations.", | ||||
|         "ALERT_TYPE": { | ||||
|           "TITLE": "Alert types:", | ||||
|           "NONE": "None", | ||||
|           "ASSIGNED": "Assigned Conversations", | ||||
|           "ALL_CONVERSATIONS": "All Conversations" | ||||
|         }, | ||||
|         "DEFAULT_TONE": { | ||||
|           "TITLE": "Default tone:" | ||||
|         }, | ||||
|         "CONDITIONS": { | ||||
|           "TITLE": "Conditions:", | ||||
|           "CONDITION_ONE": "Send audio alerts only if the browser window is not active" | ||||
|         } | ||||
|       }, | ||||
|       "EMAIL_NOTIFICATIONS_SECTION": { | ||||
|         "TITLE": "Email Notifications", | ||||
|         "NOTE": "Update your email notification preferences here", | ||||
|   | ||||
| @@ -10,6 +10,14 @@ | ||||
|         </p> | ||||
|       </div> | ||||
|       <div class="columns small-9"> | ||||
|         <div class="notification-items--wrapper"> | ||||
|           <span class="text-block-title notification-label"> | ||||
|             {{ | ||||
|               $t( | ||||
|                 'PROFILE_SETTINGS.FORM.AUDIO_NOTIFICATIONS_SECTION.ALERT_TYPE.TITLE' | ||||
|               ) | ||||
|             }} | ||||
|           </span> | ||||
|           <div> | ||||
|             <input | ||||
|               id="audio_enable_alert_none" | ||||
| @@ -20,7 +28,11 @@ | ||||
|               @input="handleAudioInput" | ||||
|             /> | ||||
|             <label for="audio_enable_alert_none"> | ||||
|             {{ $t('PROFILE_SETTINGS.FORM.AUDIO_NOTIFICATIONS_SECTION.NONE') }} | ||||
|               {{ | ||||
|                 $t( | ||||
|                   'PROFILE_SETTINGS.FORM.AUDIO_NOTIFICATIONS_SECTION.ALERT_TYPE.NONE' | ||||
|                 ) | ||||
|               }} | ||||
|             </label> | ||||
|           </div> | ||||
|           <div> | ||||
| @@ -34,7 +46,9 @@ | ||||
|             /> | ||||
|             <label for="audio_enable_alert_mine"> | ||||
|               {{ | ||||
|               $t('PROFILE_SETTINGS.FORM.AUDIO_NOTIFICATIONS_SECTION.ASSIGNED') | ||||
|                 $t( | ||||
|                   'PROFILE_SETTINGS.FORM.AUDIO_NOTIFICATIONS_SECTION.ALERT_TYPE.ASSIGNED' | ||||
|                 ) | ||||
|               }} | ||||
|             </label> | ||||
|           </div> | ||||
| @@ -50,12 +64,63 @@ | ||||
|             <label for="audio_enable_alert_all"> | ||||
|               {{ | ||||
|                 $t( | ||||
|                 'PROFILE_SETTINGS.FORM.AUDIO_NOTIFICATIONS_SECTION.ALL_CONVERSATIONS' | ||||
|                   'PROFILE_SETTINGS.FORM.AUDIO_NOTIFICATIONS_SECTION.ALERT_TYPE.ALL_CONVERSATIONS' | ||||
|                 ) | ||||
|               }} | ||||
|             </label> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="notification-items--wrapper"> | ||||
|           <span class="text-block-title notification-label"> | ||||
|             {{ | ||||
|               $t( | ||||
|                 'PROFILE_SETTINGS.FORM.AUDIO_NOTIFICATIONS_SECTION.DEFAULT_TONE.TITLE' | ||||
|               ) | ||||
|             }} | ||||
|           </span> | ||||
|           <div> | ||||
|             <select | ||||
|               v-model="notificationTone" | ||||
|               class="tone-selector" | ||||
|               @change="handleAudioToneChange" | ||||
|             > | ||||
|               <option | ||||
|                 v-for="tone in notificationAlertTones" | ||||
|                 :key="tone.value" | ||||
|                 :value="tone.value" | ||||
|               > | ||||
|                 {{ tone.label }} | ||||
|               </option> | ||||
|             </select> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="notification-items--wrapper"> | ||||
|           <span class="text-block-title notification-label"> | ||||
|             {{ | ||||
|               $t( | ||||
|                 'PROFILE_SETTINGS.FORM.AUDIO_NOTIFICATIONS_SECTION.CONDITIONS.TITLE' | ||||
|               ) | ||||
|             }} | ||||
|           </span> | ||||
|           <div> | ||||
|             <input | ||||
|               id="audio_alert_when_tab_is_inactive" | ||||
|               v-model="playAudioWhenTabIsInactive" | ||||
|               class="notification--checkbox" | ||||
|               type="checkbox" | ||||
|               value="tab_is_inactive" | ||||
|               @input="handleAudioAlertConditions" | ||||
|             /> | ||||
|             <label for="audio_alert_when_tab_is_inactive"> | ||||
|               {{ | ||||
|                 $t( | ||||
|                   'PROFILE_SETTINGS.FORM.AUDIO_NOTIFICATIONS_SECTION.CONDITIONS.CONDITION_ONE' | ||||
|                 ) | ||||
|               }} | ||||
|             </label> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <div class="profile--settings--row row"> | ||||
|       <div class="columns small-3 "> | ||||
| @@ -257,6 +322,18 @@ export default { | ||||
|       selectedPushFlags: [], | ||||
|       enableAudioAlerts: false, | ||||
|       hasEnabledPushPermissions: false, | ||||
|       playAudioWhenTabIsInactive: false, | ||||
|       notificationTone: 'ding', | ||||
|       notificationAlertTones: [ | ||||
|         { | ||||
|           value: 'ding', | ||||
|           label: 'Ding', | ||||
|         }, | ||||
|         { | ||||
|           value: 'bell', | ||||
|           label: 'Bell', | ||||
|         }, | ||||
|       ], | ||||
|     }; | ||||
|   }, | ||||
|   computed: { | ||||
| @@ -280,20 +357,27 @@ export default { | ||||
|       this.selectedPushFlags = value; | ||||
|     }, | ||||
|     uiSettings(value) { | ||||
|       const { enable_audio_alerts: enableAudio = false } = value; | ||||
|       this.enableAudioAlerts = enableAudio; | ||||
|       this.notificationUISettings(value); | ||||
|     }, | ||||
|   }, | ||||
|   mounted() { | ||||
|     if (hasPushPermissions()) { | ||||
|       this.getPushSubscription(); | ||||
|     } | ||||
|  | ||||
|     this.notificationUISettings(this.uiSettings); | ||||
|     this.$store.dispatch('userNotificationSettings/get'); | ||||
|     const { enable_audio_alerts: enableAudio = false } = this.uiSettings; | ||||
|     this.enableAudioAlerts = enableAudio; | ||||
|   }, | ||||
|   methods: { | ||||
|     notificationUISettings(uiSettings) { | ||||
|       const { | ||||
|         enable_audio_alerts: enableAudio = false, | ||||
|         always_play_audio_alert: alwaysPlayAudioAlert, | ||||
|         notification_tone: notificationTone, | ||||
|       } = uiSettings; | ||||
|       this.enableAudioAlerts = enableAudio; | ||||
|       this.playAudioWhenTabIsInactive = !alwaysPlayAudioAlert; | ||||
|       this.notificationTone = notificationTone || 'ding'; | ||||
|     }, | ||||
|     onRegistrationSuccess() { | ||||
|       this.hasEnabledPushPermissions = true; | ||||
|     }, | ||||
| @@ -351,6 +435,19 @@ export default { | ||||
|       }); | ||||
|       this.showAlert(this.$t('PROFILE_SETTINGS.FORM.API.UPDATE_SUCCESS')); | ||||
|     }, | ||||
|     handleAudioAlertConditions(e) { | ||||
|       let condition = e.target.value; | ||||
|       if (condition === 'tab_is_inactive') { | ||||
|         this.updateUISettings({ | ||||
|           always_play_audio_alert: !e.target.checked, | ||||
|         }); | ||||
|       } | ||||
|       this.showAlert(this.$t('PROFILE_SETTINGS.FORM.API.UPDATE_SUCCESS')); | ||||
|     }, | ||||
|     handleAudioToneChange(e) { | ||||
|       this.updateUISettings({ notification_tone: e.target.value }); | ||||
|       this.showAlert(this.$t('PROFILE_SETTINGS.FORM.API.UPDATE_SUCCESS')); | ||||
|     }, | ||||
|     toggleInput(selected, current) { | ||||
|       if (selected.includes(current)) { | ||||
|         const newSelectedFlags = selected.filter(flag => flag !== current); | ||||
| @@ -372,4 +469,21 @@ export default { | ||||
| .push-notification--button { | ||||
|   margin-bottom: var(--space-one); | ||||
| } | ||||
|  | ||||
| .notification-items--wrapper { | ||||
|   margin-bottom: var(--space-smaller); | ||||
| } | ||||
|  | ||||
| .notification-label { | ||||
|   display: flex; | ||||
|   font-weight: var(--font-weight-bold); | ||||
|   margin-bottom: var(--space-small); | ||||
| } | ||||
|  | ||||
| .tone-selector { | ||||
|   height: var(--space-large); | ||||
|   padding-bottom: var(--space-micro); | ||||
|   padding-top: var(--space-micro); | ||||
|   width: var(--space-mega); | ||||
| } | ||||
| </style> | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								app/javascript/shared/assets/audio/bell.mp3
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								app/javascript/shared/assets/audio/bell.mp3
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| @@ -15,10 +15,20 @@ export const getAudioContext = () => { | ||||
|   return audioCtx; | ||||
| }; | ||||
|  | ||||
| const getAlertTone = alertType => { | ||||
|   if (alertType === 'dashboard') { | ||||
|     const { | ||||
|       notification_tone: tone, | ||||
|     } = window.WOOT.$store.getters.getUISettings; | ||||
|     return tone; | ||||
|   } | ||||
|   return 'ding'; | ||||
| }; | ||||
|  | ||||
| export const getAlertAudio = async (baseUrl = '', type = 'dashboard') => { | ||||
|   const audioCtx = getAudioContext(); | ||||
|  | ||||
|   const playsound = audioBuffer => { | ||||
|   const playSound = audioBuffer => { | ||||
|     window.playAudioAlert = () => { | ||||
|       if (audioCtx) { | ||||
|         const source = audioCtx.createBufferSource(); | ||||
| @@ -31,13 +41,14 @@ export const getAlertAudio = async (baseUrl = '', type = 'dashboard') => { | ||||
|   }; | ||||
|  | ||||
|   if (audioCtx) { | ||||
|     const resourceUrl = `${baseUrl}/audio/${type}/ding.mp3`; | ||||
|     const alertTone = getAlertTone(type); | ||||
|     const resourceUrl = `${baseUrl}/audio/${type}/${alertTone}.mp3`; | ||||
|     const audioRequest = new Request(resourceUrl); | ||||
|  | ||||
|     fetch(audioRequest) | ||||
|       .then(response => response.arrayBuffer()) | ||||
|       .then(buffer => { | ||||
|         audioCtx.decodeAudioData(buffer).then(playsound); | ||||
|         audioCtx.decodeAudioData(buffer).then(playSound); | ||||
|         return new Promise(res => res()); | ||||
|       }) | ||||
|       .catch(() => { | ||||
| @@ -91,6 +102,7 @@ export const getAssigneeFromNotification = currentConv => { | ||||
|   } | ||||
|   return id; | ||||
| }; | ||||
|  | ||||
| export const newMessageNotification = data => { | ||||
|   const { conversation_id: currentConvId } = window.WOOT.$route.params; | ||||
|   const currentUserId = window.WOOT.$store.getters.getCurrentUserID; | ||||
| @@ -98,10 +110,13 @@ export const newMessageNotification = data => { | ||||
|   const currentConv = | ||||
|     window.WOOT.$store.getters.getConversationById(incomingConvId) || {}; | ||||
|   const assigneeId = getAssigneeFromNotification(currentConv); | ||||
|   const isDocHidden = document.hidden; | ||||
|  | ||||
|   const { | ||||
|     enable_audio_alerts: enableAudioAlerts = false, | ||||
|     always_play_audio_alert: alwaysPlayAudioAlert, | ||||
|   } = window.WOOT.$store.getters.getUISettings; | ||||
|   const isDocHidden = alwaysPlayAudioAlert ? true : document.hidden; | ||||
|  | ||||
|   const playAudio = shouldPlayAudio( | ||||
|     data, | ||||
|     currentConvId, | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								public/audio/dashboard/bell.mp3
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/audio/dashboard/bell.mp3
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
		Reference in New Issue
	
	Block a user