Add Desktop notifications (#252)

* Add notifications

* Abide push actions

* Handle browsers not having notification support

* Ask for notification permission after loading

* Make usePermission work without live permission support

* Focus message when clicking the notification

* make const all caps

* Fix usePermission error in Safari

* Fix live permissions

* Remove userActivity and use document.visibilityState instead

* Change setting label to "desktop notifications"

* Check for notification permissions in the settings.js
This commit is contained in:
ginnyTheCat 2022-01-29 15:20:51 +01:00 committed by GitHub
parent d0b4e092b3
commit c828dfd596
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 174 additions and 15 deletions

View file

@ -1,5 +1,8 @@
import EventEmitter from 'events';
import { selectRoom } from '../action/navigation';
import cons from './cons';
import navigation from './navigation';
import settings from './settings';
function isNotifEvent(mEvent) {
const eType = mEvent.getType();
@ -24,6 +27,9 @@ class Notifications extends EventEmitter {
this._initNoti();
this._listenEvents();
// Ask for permission by default after loading
window.Notification?.requestPermission();
// TODO:
window.notifications = this;
}
@ -158,6 +164,32 @@ class Notifications extends EventEmitter {
[...parentIds].forEach((parentId) => this._deleteNoti(parentId, total, highlight, roomId));
}
async _displayPopupNoti(mEvent, room) {
if (!settings.showNotifications) return;
const actions = this.matrixClient.getPushActionsForEvent(mEvent);
if (!actions?.notify) return;
if (navigation.selectedRoomId === room.roomId && document.visibilityState === 'visible') return;
if (mEvent.isEncrypted()) {
await mEvent.attemptDecryption(this.matrixClient.crypto);
}
let title;
if (!mEvent.sender || room.name === mEvent.sender.name) {
title = room.name;
} else if (mEvent.sender) {
title = `${mEvent.sender.name} (${room.name})`;
}
const noti = new window.Notification(title, {
body: mEvent.getContent().body,
icon: mEvent.sender?.getAvatarUrl(this.matrixClient.baseUrl, 36, 36, 'crop'),
});
noti.onclick = () => selectRoom(room.roomId, mEvent.getId());
}
_listenEvents() {
this.matrixClient.on('Room.timeline', (mEvent, room) => {
if (!isNotifEvent(mEvent)) return;
@ -172,6 +204,10 @@ class Notifications extends EventEmitter {
const noti = this.getNoti(room.roomId);
this._setNoti(room.roomId, total - noti.total, highlight - noti.highlight);
if (this.matrixClient.getSyncState() === 'SYNCING') {
this._displayPopupNoti(mEvent, room);
}
});
this.matrixClient.on('Room.receipt', (mEvent, room) => {