Merge branch 'develop' of github.com:matrix-org/synapse into develop

This commit is contained in:
Erik Johnston 2014-08-27 17:05:48 +01:00
commit 7c89d5e97a
8 changed files with 284 additions and 13 deletions

View file

@ -13,14 +13,104 @@
"token": [] "token": []
}, },
"apis": [ "apis": [
{
"path": "/rooms/{roomId}/send/{eventType}/{txnId}",
"operations": [
{
"method": "PUT",
"summary": "Send a generic non-state event to this room.",
"notes": "This operation can also be done as a POST to /rooms/{roomId}/send/{eventType}",
"type": "EventId",
"nickname": "send_non_state_event",
"consumes": [
"application/json"
],
"parameters": [
{
"name": "body",
"description": "The event contents",
"required": true,
"type": "EventContent",
"paramType": "body"
},
{
"name": "roomId",
"description": "The room to send the message in.",
"required": true,
"type": "string",
"paramType": "path"
},
{
"name": "eventType",
"description": "The type of event to send.",
"required": true,
"type": "string",
"paramType": "path"
},
{
"name": "txnId",
"description": "A client transaction ID to ensure idempotency. This can only be omitted if the HTTP method becomes a POST.",
"required": true,
"type": "string",
"paramType": "path"
}
]
}
]
},
{
"path": "/rooms/{roomId}/state/{eventType}/{stateKey}",
"operations": [
{
"method": "PUT",
"summary": "Send a generic state event to this room.",
"notes": "The state key can be omitted, such that you can PUT to /rooms/{roomId}/state/{eventType}. The state key defaults to a 0 length string in this case.",
"type": "void",
"nickname": "send_state_event",
"consumes": [
"application/json"
],
"parameters": [
{
"name": "body",
"description": "The event contents",
"required": true,
"type": "EventContent",
"paramType": "body"
},
{
"name": "roomId",
"description": "The room to send the message in.",
"required": true,
"type": "string",
"paramType": "path"
},
{
"name": "eventType",
"description": "The type of event to send.",
"required": true,
"type": "string",
"paramType": "path"
},
{
"name": "stateKey",
"description": "An identifier used to specify clobbering semantics. State events with the same (roomId, eventType, stateKey) will be replaced.",
"required": true,
"type": "string",
"paramType": "path"
}
]
}
]
},
{ {
"path": "/rooms/{roomId}/send/m.room.message/{txnId}", "path": "/rooms/{roomId}/send/m.room.message/{txnId}",
"operations": [ "operations": [
{ {
"method": "PUT", "method": "PUT",
"summary": "Send a message in this room.", "summary": "Send a message in this room.",
"notes": "Send a message in this room.", "notes": "This operation can also be done as a POST to /rooms/{roomId}/send/m.room.message",
"type": "void", "type": "EventId",
"nickname": "send_message", "nickname": "send_message",
"consumes": [ "consumes": [
"application/json" "application/json"
@ -42,7 +132,7 @@
}, },
{ {
"name": "txnId", "name": "txnId",
"description": "A client transaction ID to ensure idempotency.", "description": "A client transaction ID to ensure idempotency. This can only be omitted if the HTTP method becomes a POST.",
"required": true, "required": true,
"type": "string", "type": "string",
"paramType": "path" "paramType": "path"
@ -110,8 +200,8 @@
{ {
"method": "PUT", "method": "PUT",
"summary": "Send feedback to a message.", "summary": "Send feedback to a message.",
"notes": "Send feedback to a message.", "notes": "This operation can also be done as a POST to /rooms/{roomId}/send/m.room.message.feedback",
"type": "void", "type": "EventId",
"nickname": "send_feedback", "nickname": "send_feedback",
"consumes": [ "consumes": [
"application/json" "application/json"
@ -133,7 +223,7 @@
}, },
{ {
"name": "txnId", "name": "txnId",
"description": "A client transaction ID to ensure idempotency.", "description": "A client transaction ID to ensure idempotency. This can only be omitted if the HTTP method becomes a POST.",
"required": true, "required": true,
"type": "string", "type": "string",
"paramType": "path" "paramType": "path"
@ -488,6 +578,51 @@
] ]
} }
] ]
},
{
"path": "/rooms/{roomId}/state",
"operations": [
{
"method": "GET",
"summary": "Get a list of all the current state events for this room.",
"notes": "Get a list of all the current state events for this room.",
"type": "array",
"items": {
"$ref": "Event"
},
"nickname": "get_state_events",
"parameters": [
{
"name": "roomId",
"description": "The room to get a list of current state events from.",
"required": true,
"type": "string",
"paramType": "path"
}
]
}
]
},
{
"path": "/rooms/{roomId}/initialSync",
"operations": [
{
"method": "GET",
"summary": "Get all the current information for this room, including messages and state events.",
"notes": "Get all the current information for this room, including messages and state events.",
"type": "InitialSyncRoomData",
"nickname": "get_room_sync_data",
"parameters": [
{
"name": "roomId",
"description": "The room to get information for.",
"required": true,
"type": "string",
"paramType": "path"
}
]
}
]
} }
], ],
"models": { "models": {
@ -633,12 +768,17 @@
"properties": { "properties": {
"event_id": { "event_id": {
"type": "string", "type": "string",
"description": "An ID which uniquely identifies this event.", "description": "An ID which uniquely identifies this event. This is automatically set by the server.",
"required": true "required": true
}, },
"room_id": { "room_id": {
"type": "string", "type": "string",
"description": "The room in which this event occurred.", "description": "The room in which this event occurred. This is automatically set by the server.",
"required": true
},
"type": {
"type": "string",
"description": "The event type.",
"required": true "required": true
} }
}, },
@ -646,6 +786,26 @@
"MessageEvent" "MessageEvent"
] ]
}, },
"EventId": {
"id": "EventId",
"properties": {
"event_id": {
"type": "string",
"description": "The allocated event ID for this event.",
"required": true
}
}
},
"EventContent": {
"id": "EventContent",
"properties": {
"__event_content_keys__": {
"type": "string",
"description": "Event-specific content keys and values.",
"required": false
}
}
},
"MessageEvent": { "MessageEvent": {
"id": "MessageEvent", "id": "MessageEvent",
"properties": { "properties": {
@ -670,6 +830,34 @@
"description": "The fully-qualified user ID." "description": "The fully-qualified user ID."
} }
} }
},
"InitialSyncRoomData": {
"id": "InitialSyncRoomData",
"properties": {
"membership": {
"type": "string",
"description": "This user's membership state in this room.",
"required": true
},
"room_id": {
"type": "string",
"description": "The ID of this room.",
"required": true
},
"messages": {
"type": "MessagePaginationChunk",
"description": "The most recent messages for this room, governed by the limit parameter.",
"required": false
},
"state": {
"type": "array",
"description": "A list of state events representing the current state of the room.",
"required": false,
"items": {
"$ref": "Event"
}
}
}
} }
} }
} }

View file

@ -322,6 +322,50 @@ class RoomMessageListRestServlet(RestServlet):
defer.returnValue((200, msgs)) defer.returnValue((200, msgs))
# TODO: Needs unit testing
class RoomStateRestServlet(RestServlet):
PATTERN = client_path_pattern("/rooms/(?P<room_id>[^/]*)/state$")
@defer.inlineCallbacks
def on_GET(self, request, room_id):
user = yield self.auth.get_user_by_req(request)
# TODO: Get all the current state for this room and return in the same
# format as initial sync, that is:
# [
# { state event }, { state event }
# ]
defer.returnValue((200, []))
# TODO: Needs unit testing
class RoomInitialSyncRestServlet(RestServlet):
PATTERN = client_path_pattern("/rooms/(?P<room_id>[^/]*)/initialSync$")
@defer.inlineCallbacks
def on_GET(self, request, room_id):
user = yield self.auth.get_user_by_req(request)
# TODO: Get all the initial sync data for this room and return in the
# same format as initial sync, that is:
# {
# membership: join,
# messages: [
# chunk: [ msg events ],
# start: s_tok,
# end: e_tok
# ],
# room_id: foo,
# state: [
# { state event } , { state event }
# ]
# }
# Probably worth keeping the keys room_id and membership for parity with
# /initialSync even though they must be joined to sync this and know the
# room ID, so clients can reuse the same code (room_id and membership
# are MANDATORY for /initialSync, so the code will expect it to be
# there)
defer.returnValue((200, {}))
class RoomTriggerBackfill(RestServlet): class RoomTriggerBackfill(RestServlet):
PATTERN = client_path_pattern("/rooms/(?P<room_id>[^/]*)/backfill$") PATTERN = client_path_pattern("/rooms/(?P<room_id>[^/]*)/backfill$")
@ -436,3 +480,5 @@ def register_servlets(hs, http_server):
RoomMembershipRestServlet(hs).register(http_server) RoomMembershipRestServlet(hs).register(http_server)
RoomSendEventRestServlet(hs).register(http_server) RoomSendEventRestServlet(hs).register(http_server)
PublicRoomListRestServlet(hs).register(http_server) PublicRoomListRestServlet(hs).register(http_server)
RoomStateRestServlet(hs).register(http_server)
RoomInitialSyncRestServlet(hs).register(http_server)

View file

@ -7,6 +7,16 @@
.leftBlock { .leftBlock {
width: 8em ! important; width: 8em ! important;
font-size: 8px ! important;
}
.rightBlock {
width: 0px ! important;
display: none ! important;
}
.avatar {
width: 36px ! important;
} }
#header, #header,
@ -368,6 +378,10 @@ h1 {
background-color: #f8f8ff; background-color: #f8f8ff;
} }
.recentsRoomSelected {
background-color: #eee;
}
.recentsRoomName { .recentsRoomName {
font-size: 16px; font-size: 16px;
padding-top: 7px; padding-top: 7px;
@ -387,6 +401,15 @@ h1 {
padding-bottom: 5px; padding-bottom: 5px;
} }
/*** Recents in the room page ***/
#roomRecentsTableWrapper {
float: left;
max-width: 320px;
margin-right: 20px;
height: 100%;
overflow-y: auto;
}
/*** Profile ***/ /*** Profile ***/
.profile-avatar { .profile-avatar {

View file

@ -20,7 +20,11 @@ angular.module('RecentsController', ['matrixService', 'eventHandlerService'])
.controller('RecentsController', ['$scope', 'matrixService', 'eventHandlerService', 'eventStreamService', .controller('RecentsController', ['$scope', 'matrixService', 'eventHandlerService', 'eventStreamService',
function($scope, matrixService, eventHandlerService, eventStreamService) { function($scope, matrixService, eventHandlerService, eventStreamService) {
$scope.rooms = {}; $scope.rooms = {};
// $scope of the parent where the recents component is included can override this value
// in order to highlight a specific room in the list
$scope.recentsSelectedRoomID;
$scope.$on(eventHandlerService.MEMBER_EVENT, function(ngEvent, event, isLive) { $scope.$on(eventHandlerService.MEMBER_EVENT, function(ngEvent, event, isLive) {
var config = matrixService.config(); var config = matrixService.config();
if (event.state_key === config.user_id && event.content.membership === "invite") { if (event.state_key === config.user_id && event.content.membership === "invite") {

View file

@ -1,6 +1,9 @@
<div ng-controller="RecentsController" data-ng-init="onInit()"> <div ng-controller="RecentsController" data-ng-init="onInit()">
<table class="recentsTable"> <table class="recentsTable">
<tbody ng-repeat="(rm_id, room) in rooms | orderRecents" ng-click="goToPage('room/' + (room.room_alias ? room.room_alias : room.room_id) )" class ="recentsRoom" > <tbody ng-repeat="(rm_id, room) in rooms | orderRecents"
ng-click="goToPage('room/' + (room.room_alias ? room.room_alias : room.room_id) )"
class ="recentsRoom"
ng-class="{'recentsRoomSelected': (room.room_id === recentsSelectedRoomID)}">
<tr> <tr>
<td class="recentsRoomName"> <td class="recentsRoomName">
{{ room.room_display_name }} {{ room.room_display_name }}

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
angular.module('RoomController', ['ngSanitize', 'mUtilities']) angular.module('RoomController', ['ngSanitize', 'mFileInput', 'mUtilities'])
.controller('RoomController', ['$scope', '$http', '$timeout', '$routeParams', '$location', 'matrixService', 'eventStreamService', 'eventHandlerService', 'mFileUpload', 'mUtilities', '$rootScope', .controller('RoomController', ['$scope', '$http', '$timeout', '$routeParams', '$location', 'matrixService', 'eventStreamService', 'eventHandlerService', 'mFileUpload', 'mUtilities', '$rootScope',
function($scope, $http, $timeout, $routeParams, $location, matrixService, eventStreamService, eventHandlerService, mFileUpload, mUtilities, $rootScope) { function($scope, $http, $timeout, $routeParams, $location, matrixService, eventStreamService, eventHandlerService, mFileUpload, mUtilities, $rootScope) {
'use strict'; 'use strict';
@ -327,6 +327,9 @@ angular.module('RoomController', ['ngSanitize', 'mUtilities'])
var onInit2 = function() { var onInit2 = function() {
eventHandlerService.reInitRoom($scope.room_id); eventHandlerService.reInitRoom($scope.room_id);
// Make recents highlight the current room
$scope.recentsSelectedRoomID = $scope.room_id;
// Join the room // Join the room
matrixService.join($scope.room_id).then( matrixService.join($scope.room_id).then(
function() { function() {

View file

@ -7,7 +7,11 @@
<div id="roomName"> <div id="roomName">
{{ room_alias || room_id }} {{ room_alias || room_id }}
</div> </div>
<div id="roomRecentsTableWrapper">
<div ng-include="'recents/recents.html'"></div>
</div>
<div id="usersTableWrapper"> <div id="usersTableWrapper">
<table id="usersTable"> <table id="usersTable">
<tr ng-repeat="member in members | orderMembersList"> <tr ng-repeat="member in members | orderMembersList">

View file

@ -16,7 +16,7 @@ limitations under the License.
'use strict'; 'use strict';
angular.module('SettingsController', ['matrixService', 'mFileUpload']) angular.module('SettingsController', ['matrixService', 'mFileUpload', 'mFileInput'])
.controller('SettingsController', ['$scope', 'matrixService', 'mFileUpload', .controller('SettingsController', ['$scope', 'matrixService', 'mFileUpload',
function($scope, matrixService, mFileUpload) { function($scope, matrixService, mFileUpload) {
$scope.config = matrixService.config(); $scope.config = matrixService.config();