1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-11-28 05:03:59 +03:00

Merge pull request #851 from matrix-org/travis/e2e-notifs

Calculate encrypted notification counts
This commit is contained in:
Matthew Hodgson
2019-03-06 17:11:22 +00:00
committed by GitHub
4 changed files with 83 additions and 1 deletions

View File

@@ -228,6 +228,32 @@ function MatrixClient(opts) {
this._serverSupportsLazyLoading = null; this._serverSupportsLazyLoading = null;
this._cachedCapabilities = null; // { capabilities: {}, lastUpdated: timestamp } this._cachedCapabilities = null; // { capabilities: {}, lastUpdated: timestamp }
// The SDK doesn't really provide a clean way for events to recalculate the push
// actions for themselves, so we have to kinda help them out when they are encrypted.
// We do this so that push rules are correctly executed on events in their decrypted
// state, such as highlights when the user's name is mentioned.
this.on("Event.decrypted", (event) => {
const oldActions = event.getPushActions();
const actions = this._pushProcessor.actionsForEvent(event);
event.setPushActions(actions); // Might as well while we're here
// Ensure the unread counts are kept up to date if the event is encrypted
const oldHighlight = oldActions && oldActions.tweaks
? !!oldActions.tweaks.highlight : false;
const newHighlight = actions && actions.tweaks
? !!actions.tweaks.highlight : false;
if (oldHighlight !== newHighlight) {
const room = this.getRoom(event.getRoomId());
// TODO: Handle mentions received while the client is offline
// See also https://github.com/vector-im/riot-web/issues/9069
if (room && !room.hasUserReadEvent(this.getUserId(), event.getId())) {
const current = room.getUnreadNotificationCount("highlight");
const newCount = newHighlight ? current + 1 : current - 1;
room.setUnreadNotificationCount("highlight", newCount);
}
}
});
} }
utils.inherits(MatrixClient, EventEmitter); utils.inherits(MatrixClient, EventEmitter);
utils.extend(MatrixClient.prototype, MatrixBaseApis.prototype); utils.extend(MatrixClient.prototype, MatrixBaseApis.prototype);

View File

@@ -497,6 +497,14 @@ utils.extend(module.exports.MatrixEvent.prototype, {
this._retryDecryption = false; this._retryDecryption = false;
this._setClearData(res); this._setClearData(res);
// Before we emit the event, clear the push actions so that they can be recalculated
// by relevant code. We do this because the clear event has now changed, making it
// so that existing rules can be re-run over the applicable properties. Stuff like
// highlighting when the user's name is mentioned rely on this happening. We also want
// to set the push actions before emitting so that any notification listeners don't
// pick up the wrong contents.
this.setPushActions(null);
this.emit("Event.decrypted", this, err); this.emit("Event.decrypted", this, err);
return; return;
@@ -537,6 +545,17 @@ utils.extend(module.exports.MatrixEvent.prototype, {
decryptionResult.forwardingCurve25519KeyChain || []; decryptionResult.forwardingCurve25519KeyChain || [];
}, },
/**
* Gets the cleartext content for this event. If the event is not encrypted,
* or encryption has not been completed, this will return null.
*
* @returns {Object} The cleartext (decrypted) content for the event
*/
getClearContent: function() {
const ev = this._clearEvent;
return ev && ev.content ? ev.content : null;
},
/** /**
* Check if the event is encrypted. * Check if the event is encrypted.
* @return {boolean} True if this event is encrypted. * @return {boolean} True if this event is encrypted.

View File

@@ -1424,6 +1424,40 @@ Room.prototype.getEventReadUpTo = function(userId, ignoreSynthesized) {
return receipts["m.read"][userId].eventId; return receipts["m.read"][userId].eventId;
}; };
/**
* Determines if the given user has read a particular event ID with the known
* history of the room. This is not a definitive check as it relies only on
* what is available to the room at the time of execution.
* @param {String} userId The user ID to check the read state of.
* @param {String} eventId The event ID to check if the user read.
* @returns {Boolean} True if the user has read the event, false otherwise.
*/
Room.prototype.hasUserReadEvent = function(userId, eventId) {
const readUpToId = this.getEventReadUpTo(userId, false);
if (readUpToId === eventId) return true;
if (this.timeline.length
&& this.timeline[this.timeline.length - 1].getSender()
&& this.timeline[this.timeline.length - 1].getSender() === userId) {
// It doesn't matter where the event is in the timeline, the user has read
// it because they've sent the latest event.
return true;
}
for (let i = this.timeline.length - 1; i >= 0; --i) {
const ev = this.timeline[i];
// If we encounter the target event first, the user hasn't read it
// however if we encounter the readUpToId first then the user has read
// it. These rules apply because we're iterating bottom-up.
if (ev.getId() === eventId) return false;
if (ev.getId() === readUpToId) return true;
}
// We don't know if the user has read it, so assume not.
return false;
};
/** /**
* Get a list of receipts for the given event. * Get a list of receipts for the given event.
* @param {MatrixEvent} event the event to get receipts for * @param {MatrixEvent} event the event to get receipts for

View File

@@ -184,7 +184,10 @@ function PushProcessor(client) {
}; };
const eventFulfillsDisplayNameCondition = function(cond, ev) { const eventFulfillsDisplayNameCondition = function(cond, ev) {
const content = ev.getContent(); let content = ev.getContent();
if (ev.isEncrypted() && ev.getClearContent()) {
content = ev.getClearContent();
}
if (!content || !content.body || typeof content.body != 'string') { if (!content || !content.body || typeof content.body != 'string') {
return false; return false;
} }