From 848e6e58975f1c39fae2050631846fbf3ae7bed0 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 11 Dec 2018 21:41:15 -0700 Subject: [PATCH 1/4] Support reading custom status messages Part of https://github.com/vector-im/riot-web/issues/1528 --- src/models/room-state.js | 10 ++++++++++ src/models/user.js | 14 ++++++++++++++ src/sync.js | 10 ++++++++++ 3 files changed, 34 insertions(+) diff --git a/src/models/room-state.js b/src/models/room-state.js index ac5e20077..3dbd7ff88 100644 --- a/src/models/room-state.js +++ b/src/models/room-state.js @@ -154,6 +154,16 @@ RoomState.prototype.getMembers = function() { return utils.values(this.members); }; +/** + * Get all RoomMembers in this room, excluding the user IDs provided. + * @param {Array} excludedIds The user IDs to exclude. + * @return {Array} A list of RoomMembers. + */ +RoomState.prototype.getMembersExcept = function(excludedIds) { + return utils.values(this.members) + .filter((m) => !excludedIds.includes(m.userId)); +}; + /** * Get a room member by their user ID. * @param {string} userId The room member's user ID. diff --git a/src/models/user.js b/src/models/user.js index dbfaeb791..f4b5f7a26 100644 --- a/src/models/user.js +++ b/src/models/user.js @@ -39,6 +39,9 @@ limitations under the License. * when a user was last active. * @prop {Boolean} currentlyActive Whether we should consider lastActiveAgo to be * an approximation and that the user should be seen as active 'now' + * @prop {string} statusMessage The status message for the user, if known. This is + * different from the presenceStatusMsg in that this is not tied to + * the user's presence, and should be represented differently. * @prop {Object} events The events describing this user. * @prop {MatrixEvent} events.presence The m.presence event for this user. */ @@ -46,6 +49,7 @@ function User(userId) { this.userId = userId; this.presence = "offline"; this.presenceStatusMsg = null; + this.statusMessage = ""; this.displayName = userId; this.rawDisplayName = userId; this.avatarUrl = null; @@ -179,6 +183,16 @@ User.prototype.getLastActiveTs = function() { return this.lastPresenceTs - this.lastActiveAgo; }; +/** + * Manually set the user's status message. + * @param {MatrixEvent} event The im.vector.user_status event. + */ +User.prototype.updateStatusMessage = function(event) { + if (!event.getContent()) this.statusMessage = ""; + else this.statusMessage = event.getContent()["status"]; + this._updateModifiedTime(); +}; + /** * The User class. */ diff --git a/src/sync.js b/src/sync.js index 1ce75ba82..9d8c9a571 100644 --- a/src/sync.js +++ b/src/sync.js @@ -1172,6 +1172,16 @@ SyncApi.prototype._processSyncResponse = async function( if (e.isState() && e.getType() == "m.room.encryption" && self.opts.crypto) { await self.opts.crypto.onCryptoEvent(e); } + if (e.isState() && e.getType() === "im.vector.user_status") { + let user = client.store.getUser(e.getStateKey()); + if (user) { + user.updateStatusMessage(e); + } else { + user = createNewUser(client, e.getStateKey()); + user.updateStatusMessage(e); + client.store.storeUser(user); + } + } } await Promise.mapSeries(stateEvents, processRoomEvent); From fb65c7f4bab0ad3764657b3f4c67ab93093343f6 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 12 Dec 2018 13:21:13 -0700 Subject: [PATCH 2/4] Support setting status message in rooms that look like 1:1s Part of https://github.com/vector-im/riot-web/issues/1528 --- src/client.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/client.js b/src/client.js index 22cae3e87..9b5726f2f 100644 --- a/src/client.js +++ b/src/client.js @@ -2262,6 +2262,27 @@ MatrixClient.prototype.mxcUrlToHttp = ); }; +/** + * Sets a new status message for the user. The message may be null/falsey + * to clear the message. + * @param {string} newMessage The new message to set. + * @return {module:client.Promise} Resolves: to nothing + * @return {module:http-api.MatrixError} Rejects: with an error response. + */ +MatrixClient.prototype.setStatusMessage = function(newMessage) { + return Promise.all(this.getRooms().map((room) => { + const isJoined = room.getMyMembership() === "join"; + const looksLikeDm = room.getInvitedAndJoinedMemberCount() === 2; + if (isJoined && looksLikeDm) { + return this.sendStateEvent(room.roomId, "im.vector.user_status", { + status: newMessage, + }, this.getUserId()); + } else { + return Promise.resolve(); + } + })); +}; + /** * @param {Object} opts Options to apply * @param {string} opts.presence One of "online", "offline" or "unavailable" From 08b3dfa3b5b5d0b63272f0b80b9fdd88d0795c45 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 12 Dec 2018 23:05:03 -0700 Subject: [PATCH 3/4] Prefix the status message API with `_unstable` It's not a formal feature of Matrix yet, so we should try and avoid people relying on it. This makes it appear as a private API and is very clearly labeled as not intended for use. --- src/client.js | 2 +- src/models/user.js | 8 ++++---- src/sync.js | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/client.js b/src/client.js index 9b5726f2f..c942acb9d 100644 --- a/src/client.js +++ b/src/client.js @@ -2269,7 +2269,7 @@ MatrixClient.prototype.mxcUrlToHttp = * @return {module:client.Promise} Resolves: to nothing * @return {module:http-api.MatrixError} Rejects: with an error response. */ -MatrixClient.prototype.setStatusMessage = function(newMessage) { +MatrixClient.prototype._unstable_setStatusMessage = function(newMessage) { return Promise.all(this.getRooms().map((room) => { const isJoined = room.getMyMembership() === "join"; const looksLikeDm = room.getInvitedAndJoinedMemberCount() === 2; diff --git a/src/models/user.js b/src/models/user.js index f4b5f7a26..d1496c996 100644 --- a/src/models/user.js +++ b/src/models/user.js @@ -49,7 +49,7 @@ function User(userId) { this.userId = userId; this.presence = "offline"; this.presenceStatusMsg = null; - this.statusMessage = ""; + this._unstable_statusMessage = ""; this.displayName = userId; this.rawDisplayName = userId; this.avatarUrl = null; @@ -187,9 +187,9 @@ User.prototype.getLastActiveTs = function() { * Manually set the user's status message. * @param {MatrixEvent} event The im.vector.user_status event. */ -User.prototype.updateStatusMessage = function(event) { - if (!event.getContent()) this.statusMessage = ""; - else this.statusMessage = event.getContent()["status"]; +User.prototype._unstable_updateStatusMessage = function(event) { + if (!event.getContent()) this._unstable_statusMessage = ""; + else this._unstable_statusMessage = event.getContent()["status"]; this._updateModifiedTime(); }; diff --git a/src/sync.js b/src/sync.js index 9d8c9a571..f4ea0bf88 100644 --- a/src/sync.js +++ b/src/sync.js @@ -1175,10 +1175,10 @@ SyncApi.prototype._processSyncResponse = async function( if (e.isState() && e.getType() === "im.vector.user_status") { let user = client.store.getUser(e.getStateKey()); if (user) { - user.updateStatusMessage(e); + user._unstable_updateStatusMessage(e); } else { user = createNewUser(client, e.getStateKey()); - user.updateStatusMessage(e); + user._unstable_updateStatusMessage(e); client.store.storeUser(user); } } From 06bc6e7568403cf9d391636fa09d3256649ed918 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 13 Dec 2018 09:42:22 -0700 Subject: [PATCH 4/4] Update jsdoc to match _unstable_ prefix --- src/models/user.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/models/user.js b/src/models/user.js index d1496c996..ec2f495af 100644 --- a/src/models/user.js +++ b/src/models/user.js @@ -39,7 +39,7 @@ limitations under the License. * when a user was last active. * @prop {Boolean} currentlyActive Whether we should consider lastActiveAgo to be * an approximation and that the user should be seen as active 'now' - * @prop {string} statusMessage The status message for the user, if known. This is + * @prop {string} _unstable_statusMessage The status message for the user, if known. This is * different from the presenceStatusMsg in that this is not tied to * the user's presence, and should be represented differently. * @prop {Object} events The events describing this user.