summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--synapse/api/events/__init__.py1
-rw-r--r--synapse/handlers/_base.py1
-rw-r--r--synapse/handlers/federation.py29
-rw-r--r--synapse/handlers/room.py7
-rw-r--r--synapse/storage/_base.py5
-rw-r--r--webclient/app.css1
-rw-r--r--webclient/room/room-controller.js5
-rw-r--r--webclient/rooms/rooms-controller.js9
-rw-r--r--webclient/rooms/rooms.html2
9 files changed, 53 insertions, 7 deletions
diff --git a/synapse/api/events/__init__.py b/synapse/api/events/__init__.py
index 921fd08832..aa04dbece7 100644
--- a/synapse/api/events/__init__.py
+++ b/synapse/api/events/__init__.py
@@ -51,6 +51,7 @@ class SynapseEvent(JsonEncodedObject):
         "depth",
         "destinations",
         "origin",
+        "outlier",
     ]
 
     required_keys = [
diff --git a/synapse/handlers/_base.py b/synapse/handlers/_base.py
index c2f4685c92..3f07b5aa4a 100644
--- a/synapse/handlers/_base.py
+++ b/synapse/handlers/_base.py
@@ -24,4 +24,5 @@ class BaseHandler(object):
         self.notifier = hs.get_notifier()
         self.room_lock = hs.get_room_lock_manager()
         self.state_handler = hs.get_state_handler()
+        self.distributor = hs.get_distributor()
         self.hs = hs
diff --git a/synapse/handlers/federation.py b/synapse/handlers/federation.py
index aa3bf273f7..9cff444779 100644
--- a/synapse/handlers/federation.py
+++ b/synapse/handlers/federation.py
@@ -32,6 +32,15 @@ logger = logging.getLogger(__name__)
 class FederationHandler(BaseHandler):
 
     """Handles events that originated from federation."""
+    def __init__(self, hs):
+        super(FederationHandler, self).__init__(hs)
+
+        self.distributor.observe(
+            "user_joined_room",
+            self._on_user_joined
+        )
+
+        self.waiting_for_join_list = {}
 
     @log_function
     @defer.inlineCallbacks
@@ -103,6 +112,13 @@ class FederationHandler(BaseHandler):
             if not backfilled:
                 yield self.notifier.on_new_room_event(event, store_id)
 
+        if event.type == RoomMemberEvent.TYPE:
+            if event.membership == Membership.JOIN:
+                user = self.hs.parse_userid(event.target_user_id)
+                self.distributor.fire(
+                    "user_joined_room", user=user, room_id=event.room_id
+                )
+
 
     @log_function
     @defer.inlineCallbacks
@@ -152,8 +168,10 @@ class FederationHandler(BaseHandler):
 
         yield federation.handle_new_event(new_event)
 
-        store_id = yield self.store.persist_event(new_event)
-        self.notifier.on_new_room_event(new_event, store_id)
+        # TODO (erikj): Time out here.
+        d = defer.Deferred()
+        self.waiting_for_join_list.setdefault((joinee, room_id), []).append(d)
+        yield d
 
         try:
             yield self.store.store_room(
@@ -166,3 +184,10 @@ class FederationHandler(BaseHandler):
 
 
         defer.returnValue(True)
+
+
+    @log_function
+    def _on_user_joined(self, user, room_id):
+        waiters = self.waiting_for_join_list.get((user.to_string(), room_id), [])
+        while waiters:
+            waiters.pop().callback(None)
diff --git a/synapse/handlers/room.py b/synapse/handlers/room.py
index 6229ee9bfa..d9809bd6de 100644
--- a/synapse/handlers/room.py
+++ b/synapse/handlers/room.py
@@ -264,6 +264,10 @@ class MessageHandler(BaseHandler):
                 "room_id": event.room_id,
                 "membership": event.membership,
             }
+
+            if event.membership == Membership.INVITE:
+                d["inviter"] = event.user_id
+
             ret.append(d)
 
             if event.membership != Membership.JOIN:
@@ -279,6 +283,9 @@ class MessageHandler(BaseHandler):
                     "start": token[0],
                     "end": token[1],
                 }
+
+                current_state = yield self.store.get_current_state(event.room_id)
+                d["state"] = [c.get_dict() for c in current_state]
             except:
                 logger.exception("Failed to get snapshot")
 
diff --git a/synapse/storage/_base.py b/synapse/storage/_base.py
index 36cc57c1b8..75aab2d3b9 100644
--- a/synapse/storage/_base.py
+++ b/synapse/storage/_base.py
@@ -294,6 +294,11 @@ class SQLBaseStore(object):
 
     def _parse_event_from_row(self, row_dict):
         d = copy.deepcopy({k: v for k, v in row_dict.items() if v})
+
+        d.pop("stream_ordering", None)
+        d.pop("topological_ordering", None)
+        d.pop("processed", None)
+
         d.update(json.loads(row_dict["unrecognized_keys"]))
         d["content"] = json.loads(d["content"])
         del d["unrecognized_keys"]
diff --git a/webclient/app.css b/webclient/app.css
index d2b951d3b6..83b0c9c65a 100644
--- a/webclient/app.css
+++ b/webclient/app.css
@@ -195,6 +195,7 @@ h1 {
     border: 1px solid #d8d8d8;
     height: 31px;
     display: inline-table;
+    margin-top: -1px;
     max-width: 90%;
     font-size: 16px;
     /* word-wrap: break-word; */
diff --git a/webclient/room/room-controller.js b/webclient/room/room-controller.js
index 7de50dd960..8dea64a804 100644
--- a/webclient/room/room-controller.js
+++ b/webclient/room/room-controller.js
@@ -29,6 +29,7 @@ angular.module('RoomController', ['ngSanitize', 'mUtilities'])
         user_id: matrixService.config().user_id,
         events_from: "END", // when to start the event stream from.
         earliest_token: "END", // stores how far back we've paginated.
+        first_pagination: true, // this is toggled off when the first pagination is done
         can_paginate: true, // this is toggled off when we run out of items
         paginating: false, // used to avoid concurrent pagination requests pulling in dup contents
         stream_failure: undefined, // the response when the stream fails
@@ -100,7 +101,6 @@ angular.module('RoomController', ['ngSanitize', 'mUtilities'])
         var originalTopRow = $("#messageTable>tbody>tr:first")[0];
         matrixService.paginateBackMessages($scope.room_id, $scope.state.earliest_token, numItems).then(
             function(response) {
-                var firstPagination = !$scope.events.rooms[$scope.room_id];
                 eventHandlerService.handleEvents(response.data.chunk, false);
                 $scope.state.earliest_token = response.data.end;
                 if (response.data.chunk.length < MESSAGES_PER_PAGINATION) {
@@ -126,8 +126,9 @@ angular.module('RoomController', ['ngSanitize', 'mUtilities'])
                     }, 0);
                 }
                 
-                if (firstPagination) {
+                if ($scope.state.first_pagination) {
                     scrollToBottom();
+                    $scope.state.first_pagination = false;
                 }
                 else {
                     // lock the scroll position
diff --git a/webclient/rooms/rooms-controller.js b/webclient/rooms/rooms-controller.js
index c25e24c8bc..f2ff4a25ba 100644
--- a/webclient/rooms/rooms-controller.js
+++ b/webclient/rooms/rooms-controller.js
@@ -59,7 +59,7 @@ angular.module('RoomsController', ['matrixService', 'mFileInput', 'mFileUpload',
             // FIXME push membership to top level key to match /im/sync
             event.membership = event.content.membership;
             // FIXME bodge a nicer name than the room ID for this invite.
-            event.room_alias = event.user_id + "'s room";
+            event.room_display_name = event.user_id + "'s room";
             $scope.rooms[event.room_id] = event;
         }
     });
@@ -70,15 +70,20 @@ angular.module('RoomsController', ['matrixService', 'mFileInput', 'mFileUpload',
             if (alias) {
                 // use the existing alias from storage
                 data[i].room_alias = alias;
+                data[i].room_display_name = alias;
             }
             else if (data[i].aliases && data[i].aliases[0]) {
                 // save the mapping
                 // TODO: select the smarter alias from the array
                 matrixService.createRoomIdToAliasMapping(data[i].room_id, data[i].aliases[0]);
+                data[i].room_display_name = data[i].aliases[0];
+            }
+            else if (data[i].membership == "invite" && "inviter" in data[i]) {
+                data[i].room_display_name = data[i].inviter + "'s room"
             }
             else {
                 // last resort use the room id
-                data[i].room_alias = data[i].room_id;
+                data[i].room_display_name = data[i].room_id;
             }
         }
         return data;
diff --git a/webclient/rooms/rooms.html b/webclient/rooms/rooms.html
index 2602209bd3..ba3b7d8bad 100644
--- a/webclient/rooms/rooms.html
+++ b/webclient/rooms/rooms.html
@@ -65,7 +65,7 @@
     
     <div class="rooms" ng-repeat="(rm_id, room) in rooms">
         <div>
-            <a href="#/room/{{ room.room_alias ? room.room_alias : rm_id }}" >{{ room.room_alias }}</a> {{room.membership === 'invite' ? ' (invited)' : ''}}
+            <a href="#/room/{{ room.room_alias ? room.room_alias : rm_id }}" >{{ room.room_display_name }}</a> {{room.membership === 'invite' ? ' (invited)' : ''}}
         </div>
     </div>
     <br/>