Browse Source

Desktop Notifications

When user enters a chat room, app prompts for notification permissions.
Then, if app doesn't have focus and a message arrives, a desktop summary
notification is shown.
develop
Rob Colbert 1 year ago
parent
commit
b0d28c8a2e
  1. 37
      client/js/chat-client.js

37
client/js/chat-client.js

@ -32,6 +32,8 @@ export class ChatApp extends DtpApp {
this.loadSettings(); this.loadSettings();
this.log.info('constructor', 'DTP app client online'); this.log.info('constructor', 'DTP app client online');
this.notificationPermission = 'default';
this.chat = { this.chat = {
form: document.querySelector('#chat-input-form'), form: document.querySelector('#chat-input-form'),
messageList: document.querySelector('#chat-message-list'), messageList: document.querySelector('#chat-message-list'),
@ -63,9 +65,22 @@ export class ChatApp extends DtpApp {
window.addEventListener('dtp-load', this.onDtpLoad.bind(this)); window.addEventListener('dtp-load', this.onDtpLoad.bind(this));
window.addEventListener('unload', this.onDtpUnload.bind(this)); window.addEventListener('unload', this.onDtpUnload.bind(this));
window.addEventListener('focus', this.onWindowFocus.bind(this));
window.addEventListener('blur', this.onWindowBlur.bind(this));
this.updateTimestamps(); this.updateTimestamps();
} }
async onWindowFocus (event) {
this.log.debug('onWindowFocus', 'window has received focus', { event });
this.haveFocus = true;
}
async onWindowBlur (event) {
this.log.debug('onWindowBlur', 'window has lost focus', { event });
this.haveFocus = false;
}
async startAudio ( ) { async startAudio ( ) {
this.log.info('startAudio', 'starting ChatAudio'); this.log.info('startAudio', 'starting ChatAudio');
this.audio = new ChatAudio(); this.audio = new ChatAudio();
@ -294,18 +309,28 @@ export class ChatApp extends DtpApp {
}); });
await this.processResponse(response); await this.processResponse(response);
} catch (error) { } catch (error) {
this.log.error('sendEmojiReact', 'failed to send emoji react', { error }); this.log.error('toggleMessageReaction', 'failed to send emoji react', { error });
UIkit.modal.alert(`Failed to send emoji react: ${error.message}`); UIkit.modal.alert(`Failed to send emoji react: ${error.message}`);
} }
} }
async onDtpLoad ( ) { async onDtpLoad ( ) {
this.log.info('dtp-load event received. Connecting to platform.'); this.log.info('onDtpLoad', 'dtp-load event received. Connecting to platform.');
await this.connect({ await this.connect({
mode: 'User', mode: 'User',
onSocketConnect: this.onChatSocketConnect.bind(this), onSocketConnect: this.onChatSocketConnect.bind(this),
onSocketDisconnect: this.onChatSocketDisconnect.bind(this), onSocketDisconnect: this.onChatSocketDisconnect.bind(this),
}); });
if (this.chat.messageList) {
try {
this.notificationPermission = await Notification.requestPermission();
this.log.debug('onDtpLoad', 'Notification permission status', { permission: this.notificationPermission });
} catch (error) {
this.log.error('onDtpLoad', 'failed to request Notification permission', { error });
}
}
} }
async onDtpUnload ( ) { async onDtpUnload ( ) {
@ -332,10 +357,16 @@ export class ChatApp extends DtpApp {
async onChatMessage (message) { async onChatMessage (message) {
const isAtBottom = this.chat.isAtBottom; const isAtBottom = this.chat.isAtBottom;
this.log.info('onChatMessage', 'chat message received', { message });
this.chat.messageList.insertAdjacentHTML('beforeend', message.html); this.chat.messageList.insertAdjacentHTML('beforeend', message.html);
this.audio.playSound(ChatApp.SFX_CHAT_MESSAGE); this.audio.playSound(ChatApp.SFX_CHAT_MESSAGE);
this.scrollChatToBottom(isAtBottom); this.scrollChatToBottom(isAtBottom);
if (!this.haveFocus && (this.notificationPermission === 'granted')) {
const chatMessage = message.message;
new Notification(chatMessage.channel.name, {
body: `Message received from ${chatMessage.author.displayName || chatMessage.author.username}`,
});
}
} }
async onChatControl (message) { async onChatControl (message) {

Loading…
Cancel
Save