Fix notifications for encrypted events (#1336)

Remember events that we may need to notify for once decrypted and
evaluate them in an Event.decrypted listener.
This commit is contained in:
David Baker 2017-08-24 14:27:38 +01:00 committed by Richard van der Hoff
parent 814e08d843
commit 939889705e

View file

@ -33,9 +33,16 @@ import Modal from './Modal';
* } * }
*/ */
const MAX_PENDING_ENCRYPTED = 20;
const Notifier = { const Notifier = {
notifsByRoom: {}, notifsByRoom: {},
// A list of event IDs that we've received but need to wait until
// they're decrypted until we decide whether to notify for them
// or not
pendingEncryptedEventIds: [],
notificationMessageForEvent: function(ev) { notificationMessageForEvent: function(ev) {
return TextForEvent.textForEvent(ev); return TextForEvent.textForEvent(ev);
}, },
@ -98,8 +105,10 @@ const Notifier = {
this.boundOnRoomTimeline = this.onRoomTimeline.bind(this); this.boundOnRoomTimeline = this.onRoomTimeline.bind(this);
this.boundOnSyncStateChange = this.onSyncStateChange.bind(this); this.boundOnSyncStateChange = this.onSyncStateChange.bind(this);
this.boundOnRoomReceipt = this.onRoomReceipt.bind(this); this.boundOnRoomReceipt = this.onRoomReceipt.bind(this);
this.boundOnEventDecrypted = this.onEventDecrypted.bind(this);
MatrixClientPeg.get().on('Room.timeline', this.boundOnRoomTimeline); MatrixClientPeg.get().on('Room.timeline', this.boundOnRoomTimeline);
MatrixClientPeg.get().on('Room.receipt', this.boundOnRoomReceipt); MatrixClientPeg.get().on('Room.receipt', this.boundOnRoomReceipt);
MatrixClientPeg.get().on('Event.decrypted', this.boundOnEventDecrypted);
MatrixClientPeg.get().on("sync", this.boundOnSyncStateChange); MatrixClientPeg.get().on("sync", this.boundOnSyncStateChange);
this.toolbarHidden = false; this.toolbarHidden = false;
this.isSyncing = false; this.isSyncing = false;
@ -109,6 +118,7 @@ const Notifier = {
if (MatrixClientPeg.get() && this.boundOnRoomTimeline) { if (MatrixClientPeg.get() && this.boundOnRoomTimeline) {
MatrixClientPeg.get().removeListener('Room.timeline', this.boundOnRoomTimeline); MatrixClientPeg.get().removeListener('Room.timeline', this.boundOnRoomTimeline);
MatrixClientPeg.get().removeListener('Room.receipt', this.boundOnRoomReceipt); MatrixClientPeg.get().removeListener('Room.receipt', this.boundOnRoomReceipt);
MatrixClientPeg.get().removeListener('Event.decrypted', this.boundOnEventDecrypted);
MatrixClientPeg.get().removeListener('sync', this.boundOnSyncStateChange); MatrixClientPeg.get().removeListener('sync', this.boundOnSyncStateChange);
} }
this.isSyncing = false; this.isSyncing = false;
@ -244,16 +254,26 @@ const Notifier = {
if (ev.sender && ev.sender.userId === MatrixClientPeg.get().credentials.userId) return; if (ev.sender && ev.sender.userId === MatrixClientPeg.get().credentials.userId) return;
if (data.timeline.getTimelineSet() !== room.getUnfilteredTimelineSet()) return; if (data.timeline.getTimelineSet() !== room.getUnfilteredTimelineSet()) return;
const actions = MatrixClientPeg.get().getPushActionsForEvent(ev); // If it's an encrypted event and the type is still 'm.room.encrypted',
if (actions && actions.notify) { // it hasn't yet been decrypted, so wait until it is.
if (this.isEnabled()) { if (event.isBeingDecrypted() || event.isDecryptionFailure()) {
this._displayPopupNotification(ev, room); this.pendingEncryptedEventIds.push(ev.getId());
} // don't let the list fill up indefinitely
if (actions.tweaks.sound && this.isAudioEnabled()) { while (this.pendingEncryptedEventIds.length > MAX_PENDING_ENCRYPTED) {
PlatformPeg.get().loudNotification(ev, room); this.pendingEncryptedEventIds.shift();
this._playAudioNotification(ev, room);
} }
return;
} }
this._evaluateEvent(ev);
},
onEventDecrypted: function(ev) {
const idx = this.pendingEncryptedEventIds.indexOf(ev.getId());
if (idx === -1) return;
this.pendingEncryptedEventIds.splice(idx, 1);
this._evaluateEvent(ev);
}, },
onRoomReceipt: function(ev, room) { onRoomReceipt: function(ev, room) {
@ -273,6 +293,20 @@ const Notifier = {
delete this.notifsByRoom[room.roomId]; delete this.notifsByRoom[room.roomId];
} }
}, },
_evaluateEvent: function(ev) {
const room = MatrixClientPeg.get().getRoom(ev.getRoomId());
const actions = MatrixClientPeg.get().getPushActionsForEvent(ev);
if (actions && actions.notify) {
if (this.isEnabled()) {
this._displayPopupNotification(ev, room);
}
if (actions.tweaks.sound && this.isAudioEnabled()) {
PlatformPeg.get().loudNotification(ev, room);
this._playAudioNotification(ev, room);
}
}
}
}; };
if (!global.mxNotifier) { if (!global.mxNotifier) {