Bug 1346519 - Auto-join Matrix rooms. r=pmorris
authorPatrick Cloke <clokep@gmail.com>
Wed, 30 Oct 2019 08:08:31 -0400
changeset 37391 1902ef02323e01c66123dcc658181e842fd6f564
parent 37390 013567062ce386e4cd11c35b8c02e00d9d094b85
child 37392 7c267fcfa4826158825055e2ecbf2a3702ed2e80
push id396
push userclokep@gmail.com
push dateMon, 06 Jan 2020 23:11:57 +0000
reviewerspmorris
bugs1346519
Bug 1346519 - Auto-join Matrix rooms. r=pmorris
chat/protocols/matrix/matrix.js
--- a/chat/protocols/matrix/matrix.js
+++ b/chat/protocols/matrix/matrix.js
@@ -76,24 +76,31 @@ MatrixConversation.prototype = {
 
     let participant = new MatrixParticipant(aRoomMember);
     this._participants.set(aRoomMember.userId, participant);
     this.notifyObservers(
       new nsSimpleEnumerator([participant]),
       "chat-buddy-add"
     );
   },
-  initListOfParticipants() {
-    let conv = this;
+
+  /*
+   * Initialize the room after the response from the Matrix client.
+   */
+  initRoom(aRoom) {
+    // Store the ID of the room to look up information in the future.
+    this._roomId = aRoom.roomId;
+
+    // If there are any participants, create them.
     let participants = [];
-    this.room.getJoinedMembers().forEach(function(aRoomMember) {
-      if (!conv._participants.has(aRoomMember.userId)) {
+    aRoom.getJoinedMembers().forEach(aRoomMember => {
+      if (!this._participants.has(aRoomMember.userId)) {
         let participant = new MatrixParticipant(aRoomMember);
         participants.push(participant);
-        conv._participants.set(aRoomMember.userId, participant);
+        this._participants.set(aRoomMember.userId, participant);
       }
     });
     if (participants.length) {
       this.notifyObservers(
         new nsSimpleEnumerator(participants),
         "chat-buddy-add"
       );
     }
@@ -170,38 +177,43 @@ MatrixAccount.prototype = {
         // TODO: Handle other states (RECONNECTING, ERROR, SYNCING).
       }
     });
     this._client.on("RoomMember.membership", (event, member, oldMembership) => {
       if (member.roomId in this._roomList) {
         var room = this._roomList[member.roomId];
         if (member.membership === "join") {
           room.addParticipant(member);
-        } else {
+        } else if (member.membership === "leave") {
           room.removeParticipant(member.userId);
         }
+        // Other options include "invite".
       }
     });
-    this._client.on("Room.timeline", (event, room, toStartOfTimeline) => {
-      // TODO: Better handle messages!
-      if (toStartOfTimeline) {
-        return;
+    this._client.on(
+      "Room.timeline",
+      (event, room, toStartOfTimeline, removed, data) => {
+        // TODO: Better handle messages!
+        if (toStartOfTimeline) {
+          return;
+        }
+        if (room.roomId in this._roomList) {
+          let body;
+          if (event.getType() === "m.room.message") {
+            body = event.getContent().body;
+          } else {
+            // TODO Any event that is not understood gets the raw content added to the conversation.
+            body = JSON.stringify(event.getContent());
+          }
+          this._roomList[room.roomId].writeMessage(event.getSender(), body, {
+            incoming: true,
+          });
+        }
       }
-      if (room.roomId in this._roomList) {
-        let body;
-        if (event.getType() === "m.room.message") {
-          body = event.getContent().body;
-        } else {
-          body = JSON.stringify(event.getContent());
-        }
-        this._roomList[room.roomId].writeMessage(event.getSender(), body, {
-          incoming: true,
-        });
-      }
-    });
+    );
     // Update the chat participant information.
     this._client.on("RoomMember.name", this.updateRoomMember);
     this._client.on("RoomMember.powerLevel", this.updateRoomMember);
 
     // TODO Other events to handle:
     //  Room.accountData
     //  Room.localEchoUpdated
     //  Room.name
@@ -210,16 +222,28 @@ MatrixAccount.prototype = {
     //  RoomMember.typing
     //  Session.logged_out
     //  User.avatarUrl
     //  User.currentlyActive
     //  User.displayName
     //  User.presence
 
     this._client.startClient();
+
+    // Get the list of joined rooms on the server and create those conversations.
+    this._client.getJoinedRooms().then(response => {
+      for (let roomId of response.joined_rooms) {
+        let conv = new MatrixConversation(this, roomId, this.userId);
+        this._roomList[roomId] = conv;
+        let room = this._client.getRoom(roomId);
+        if (room) {
+          conv.initRoom(room);
+        }
+      }
+    });
   },
 
   updateRoomMember(event, member) {
     if (member.roomId in this._roomList) {
       let conv = this._roomList[member.roomId];
       let participant = conv._participants.get(member.userId);
       // A participant might not exist (for example, this happens if the user
       // has only been invited, but has not yet joined).
@@ -259,37 +283,37 @@ MatrixAccount.prototype = {
     let roomIdOrAlias = aComponents.getValue("roomIdOrAlias").trim();
     let domain = this._client.getDomain();
     // For the format of room id and alias, see the matrix documentation:
     // https://matrix.org/docs/spec/intro.html#room-structure
     // https://matrix.org/docs/spec/intro.html#room-aliases
     if (!roomIdOrAlias.endsWith(":" + domain)) {
       roomIdOrAlias += ":" + domain;
     }
-    if (!roomIdOrAlias.match("^[!#]")) {
+    if (!roomIdOrAlias.match(/^[!#]/)) {
       roomIdOrAlias = "#" + roomIdOrAlias;
     }
 
     // TODO: Use getRoom to find existing conversation?
     let conv = new MatrixConversation(this, roomIdOrAlias, this.userId);
     conv.joining = true;
     this._client
       .joinRoom(roomIdOrAlias)
       .then(room => {
-        conv._roomId = room.roomId;
         this._roomList[room.roomId] = conv;
-        conv.initListOfParticipants();
+        conv.initRoom(room);
         conv.joining = false;
       })
       .catch(error => {
         // TODO: Handle errors?
         // XXX We probably want to display an error in the open conversation
-        //     window and leave it as unjoined.
+        //     window.
         this.ERROR(error);
-        conv.close();
+        conv.joining = false;
+        conv.left = true;
 
         // TODO Perhaps we should call createRoom if the room doesn't exist.
       });
     return conv;
   },
   createConversation(aName) {
     throw Cr.NS_ERROR_NOT_IMPLEMENTED;
   },