mirror of
https://github.com/lingble/chatwoot.git
synced 2025-10-30 18:47:51 +00:00
218 lines
6.1 KiB
JavaScript
218 lines
6.1 KiB
JavaScript
import { MESSAGE_TYPE } from 'shared/constants/messages';
|
|
import { showBadgeOnFavicon } from './faviconHelper';
|
|
import { initFaviconSwitcher } from './faviconHelper';
|
|
|
|
import { EVENT_TYPES } from 'dashboard/routes/dashboard/settings/profile/constants.js';
|
|
import GlobalStore from 'dashboard/store';
|
|
import AudioNotificationStore from './AudioNotificationStore';
|
|
import {
|
|
isConversationAssignedToMe,
|
|
isConversationUnassigned,
|
|
isMessageFromCurrentUser,
|
|
} from './AudioMessageHelper';
|
|
import WindowVisibilityHelper from './WindowVisibilityHelper';
|
|
import { useAlert } from 'dashboard/composables';
|
|
|
|
const NOTIFICATION_TIME = 30000;
|
|
const ALERT_DURATION = 10000;
|
|
const ALERT_PATH_PREFIX = '/audio/dashboard/';
|
|
const DEFAULT_TONE = 'ding';
|
|
const DEFAULT_ALERT_TYPE = ['none'];
|
|
|
|
export class DashboardAudioNotificationHelper {
|
|
constructor(store) {
|
|
if (!store) {
|
|
throw new Error('store is required');
|
|
}
|
|
this.store = new AudioNotificationStore(store);
|
|
|
|
this.notificationConfig = {
|
|
audioAlertType: DEFAULT_ALERT_TYPE,
|
|
playAlertOnlyWhenHidden: true,
|
|
alertIfUnreadConversationExist: false,
|
|
};
|
|
|
|
this.recurringNotificationTimer = null;
|
|
|
|
this.audioConfig = {
|
|
audio: null,
|
|
tone: DEFAULT_TONE,
|
|
hasSentSoundPermissionsRequest: false,
|
|
};
|
|
|
|
this.currentUser = null;
|
|
}
|
|
|
|
intializeAudio = () => {
|
|
const resourceUrl = `${ALERT_PATH_PREFIX}${this.audioConfig.tone}.mp3`;
|
|
this.audioConfig.audio = new Audio(resourceUrl);
|
|
return this.audioConfig.audio.load();
|
|
};
|
|
|
|
playAudioAlert = async () => {
|
|
try {
|
|
await this.audioConfig.audio.play();
|
|
} catch (error) {
|
|
if (
|
|
error.name === 'NotAllowedError' &&
|
|
!this.hasSentSoundPermissionsRequest
|
|
) {
|
|
this.hasSentSoundPermissionsRequest = true;
|
|
useAlert(
|
|
'PROFILE_SETTINGS.FORM.AUDIO_NOTIFICATIONS_SECTION.SOUND_PERMISSION_ERROR',
|
|
{ usei18n: true, duration: ALERT_DURATION }
|
|
);
|
|
}
|
|
}
|
|
};
|
|
|
|
set = ({
|
|
currentUser,
|
|
alwaysPlayAudioAlert,
|
|
alertIfUnreadConversationExist,
|
|
audioAlertType = DEFAULT_ALERT_TYPE,
|
|
audioAlertTone = DEFAULT_TONE,
|
|
}) => {
|
|
this.notificationConfig = {
|
|
...this.notificationConfig,
|
|
audioAlertType: audioAlertType.split('+').filter(Boolean),
|
|
playAlertOnlyWhenHidden: !alwaysPlayAudioAlert,
|
|
alertIfUnreadConversationExist: alertIfUnreadConversationExist,
|
|
};
|
|
|
|
this.currentUser = currentUser;
|
|
|
|
const previousAudioTone = this.audioConfig.tone;
|
|
this.audioConfig = {
|
|
...this.audioConfig,
|
|
tone: audioAlertTone,
|
|
};
|
|
|
|
if (previousAudioTone !== audioAlertTone) {
|
|
this.intializeAudio();
|
|
}
|
|
|
|
initFaviconSwitcher();
|
|
this.clearRecurringTimer();
|
|
this.playAudioEvery30Seconds();
|
|
};
|
|
|
|
shouldPlayAlert = () => {
|
|
if (this.notificationConfig.playAlertOnlyWhenHidden) {
|
|
return !WindowVisibilityHelper.isWindowVisible();
|
|
}
|
|
return true;
|
|
};
|
|
|
|
executeRecurringNotification = () => {
|
|
if (this.store.hasUnreadConversation() && this.shouldPlayAlert()) {
|
|
this.playAudioAlert();
|
|
showBadgeOnFavicon();
|
|
}
|
|
this.resetRecurringTimer();
|
|
};
|
|
|
|
clearRecurringTimer = () => {
|
|
if (this.recurringNotificationTimer) {
|
|
clearTimeout(this.recurringNotificationTimer);
|
|
}
|
|
};
|
|
|
|
resetRecurringTimer = () => {
|
|
this.clearRecurringTimer();
|
|
this.recurringNotificationTimer = setTimeout(
|
|
this.executeRecurringNotification,
|
|
NOTIFICATION_TIME
|
|
);
|
|
};
|
|
|
|
playAudioEvery30Seconds = () => {
|
|
const { audioAlertType, alertIfUnreadConversationExist } =
|
|
this.notificationConfig;
|
|
|
|
// Audio alert is disabled dismiss the timer
|
|
if (audioAlertType.includes('none')) return;
|
|
|
|
// If unread conversation flag is disabled, dismiss the timer
|
|
if (!alertIfUnreadConversationExist) return;
|
|
|
|
this.resetRecurringTimer();
|
|
};
|
|
|
|
shouldNotifyOnMessage = message => {
|
|
const { audioAlertType } = this.notificationConfig;
|
|
if (audioAlertType.includes('none')) return false;
|
|
if (audioAlertType.includes('all')) return true;
|
|
|
|
const assignedToMe = isConversationAssignedToMe(
|
|
message,
|
|
this.currentUser.id
|
|
);
|
|
const isUnassigned = isConversationUnassigned(message);
|
|
|
|
const shouldPlayAudio = [];
|
|
|
|
if (
|
|
audioAlertType.includes(EVENT_TYPES.ASSIGNED) ||
|
|
audioAlertType.includes('mine')
|
|
) {
|
|
shouldPlayAudio.push(assignedToMe);
|
|
}
|
|
if (audioAlertType.includes(EVENT_TYPES.UNASSIGNED)) {
|
|
shouldPlayAudio.push(isUnassigned);
|
|
}
|
|
if (audioAlertType.includes(EVENT_TYPES.NOTME)) {
|
|
shouldPlayAudio.push(!isUnassigned && !assignedToMe);
|
|
}
|
|
|
|
return shouldPlayAudio.some(Boolean);
|
|
};
|
|
|
|
onNewMessage = message => {
|
|
// If the user does not have the permission to view the conversation, then dismiss the alert
|
|
// FIX ME: There shouldn't be a new message if the user has no access to the conversation.
|
|
if (!this.store.hasConversationPermission(this.currentUser)) {
|
|
return;
|
|
}
|
|
|
|
// If the conversation status is pending, then dismiss the alert
|
|
// This case is common for all audio event types
|
|
if (this.store.isMessageFromPendingConversation(message)) {
|
|
return;
|
|
}
|
|
|
|
// If the message is sent by the current user then dismiss the alert
|
|
if (isMessageFromCurrentUser(message, this.currentUser.id)) {
|
|
return;
|
|
}
|
|
|
|
if (!this.shouldNotifyOnMessage(message)) {
|
|
return;
|
|
}
|
|
|
|
// If the message type is not incoming or private, then dismiss the alert
|
|
const { message_type: messageType, private: isPrivate } = message;
|
|
if (messageType !== MESSAGE_TYPE.INCOMING && !isPrivate) {
|
|
return;
|
|
}
|
|
|
|
if (WindowVisibilityHelper.isWindowVisible()) {
|
|
// If the user looking at the conversation, then dismiss the alert
|
|
if (this.store.isMessageFromCurrentConversation(message)) {
|
|
return;
|
|
}
|
|
|
|
// If the user has disabled alerts when active on the dashboard, the dismiss the alert
|
|
if (this.notificationConfig.playAlertOnlyWhenHidden) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
this.playAudioAlert();
|
|
showBadgeOnFavicon();
|
|
this.playAudioEvery30Seconds();
|
|
};
|
|
}
|
|
|
|
export default new DashboardAudioNotificationHelper(GlobalStore);
|