Merge branch 'develop' of github.com:matrix-org/synapse into stream_refactor
commit
08881d808d
|
@ -15,8 +15,7 @@
|
|||
|
||||
|
||||
from . import (
|
||||
room, events, register, login, profile, public, presence, initial_sync,
|
||||
directory
|
||||
room, events, register, login, profile, presence, initial_sync, directory
|
||||
)
|
||||
|
||||
|
||||
|
@ -40,7 +39,6 @@ class RestServletFactory(object):
|
|||
register.register_servlets(hs, client_resource)
|
||||
login.register_servlets(hs, client_resource)
|
||||
profile.register_servlets(hs, client_resource)
|
||||
public.register_servlets(hs, client_resource)
|
||||
presence.register_servlets(hs, client_resource)
|
||||
initial_sync.register_servlets(hs, client_resource)
|
||||
directory.register_servlets(hs, client_resource)
|
||||
|
|
|
@ -31,7 +31,7 @@ def register_servlets(hs, http_server):
|
|||
|
||||
|
||||
class ClientDirectoryServer(RestServlet):
|
||||
PATTERN = client_path_pattern("/ds/room/(?P<room_alias>[^/]*)$")
|
||||
PATTERN = client_path_pattern("/directory/room/(?P<room_alias>[^/]*)$")
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def on_GET(self, request, room_alias):
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2014 matrix.org
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""This module contains REST servlets to do with public paths: /public"""
|
||||
from twisted.internet import defer
|
||||
|
||||
from base import RestServlet, client_path_pattern
|
||||
|
||||
|
||||
class PublicRoomListRestServlet(RestServlet):
|
||||
PATTERN = client_path_pattern("/public/rooms$")
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def on_GET(self, request):
|
||||
handler = self.handlers.room_list_handler
|
||||
data = yield handler.get_public_room_list()
|
||||
defer.returnValue((200, data))
|
||||
|
||||
|
||||
def register_servlets(hs, http_server):
|
||||
PublicRoomListRestServlet(hs).register(http_server)
|
|
@ -264,6 +264,17 @@ class JoinRoomAliasServlet(RestServlet):
|
|||
defer.returnValue(response)
|
||||
|
||||
|
||||
# TODO: Needs unit testing
|
||||
class PublicRoomListRestServlet(RestServlet):
|
||||
PATTERN = client_path_pattern("/publicRooms$")
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def on_GET(self, request):
|
||||
handler = self.handlers.room_list_handler
|
||||
data = yield handler.get_public_room_list()
|
||||
defer.returnValue((200, data))
|
||||
|
||||
|
||||
# TODO: Needs unit testing
|
||||
class RoomMemberListRestServlet(RestServlet):
|
||||
PATTERN = client_path_pattern("/rooms/(?P<room_id>[^/]*)/members$")
|
||||
|
@ -424,3 +435,4 @@ def register_servlets(hs, http_server):
|
|||
RoomTriggerBackfill(hs).register(http_server)
|
||||
RoomMembershipRestServlet(hs).register(http_server)
|
||||
RoomSendEventRestServlet(hs).register(http_server)
|
||||
PublicRoomListRestServlet(hs).register(http_server)
|
||||
|
|
|
@ -37,7 +37,11 @@ angular.module('MatrixWebClientController', ['matrixService', 'mPresence', 'even
|
|||
mPresence.start();
|
||||
}
|
||||
|
||||
$scope.go = function(url) {
|
||||
/**
|
||||
* Open a given page.
|
||||
* @param {String} url url of the page
|
||||
*/
|
||||
$scope.goToPage = function(url) {
|
||||
$location.url(url);
|
||||
};
|
||||
|
||||
|
|
|
@ -342,6 +342,51 @@ h1 {
|
|||
top: 0;
|
||||
}
|
||||
|
||||
/*** Recents ***/
|
||||
.recentsTable {
|
||||
max-width: 480px;
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
.recentsTable tr {
|
||||
width: 100%;
|
||||
}
|
||||
.recentsTable td {
|
||||
vertical-align: text-top;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.recentsRoom {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.recentsRoom:hover {
|
||||
background-color: #f8f8ff;
|
||||
}
|
||||
|
||||
.recentsRoomName {
|
||||
font-size: 16px;
|
||||
padding-top: 7px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.recentsRoomSummaryTS {
|
||||
color: #888;
|
||||
font-size: 12px;
|
||||
width: 7em;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.recentsRoomSummary {
|
||||
color: #888;
|
||||
font-size: 12px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
/*** Profile ***/
|
||||
|
||||
.profile-avatar {
|
||||
|
|
|
@ -20,6 +20,7 @@ var matrixWebClient = angular.module('matrixWebClient', [
|
|||
'LoginController',
|
||||
'RoomController',
|
||||
'HomeController',
|
||||
'RecentsController',
|
||||
'SettingsController',
|
||||
'UserController',
|
||||
'matrixService',
|
||||
|
|
|
@ -106,11 +106,20 @@ angular.module('matrixService', [])
|
|||
},
|
||||
|
||||
// List all rooms joined or been invited to
|
||||
rooms: function(from, to, limit) {
|
||||
rooms: function(limit, feedback) {
|
||||
// The REST path spec
|
||||
|
||||
var path = "/initialSync";
|
||||
|
||||
return doRequest("GET", path);
|
||||
var params = {};
|
||||
if (limit) {
|
||||
params.limit = limit;
|
||||
}
|
||||
if (feedback) {
|
||||
params.feedback = feedback;
|
||||
}
|
||||
|
||||
return doRequest("GET", path, params);
|
||||
},
|
||||
|
||||
// Joins a room
|
||||
|
@ -155,7 +164,7 @@ angular.module('matrixService', [])
|
|||
|
||||
// Retrieves the room ID corresponding to a room alias
|
||||
resolveRoomAlias:function(room_alias) {
|
||||
var path = "/matrix/client/api/v1/ds/room/$room_alias";
|
||||
var path = "/matrix/client/api/v1/directory/room/$room_alias";
|
||||
room_alias = encodeURIComponent(room_alias);
|
||||
|
||||
path = path.replace("$room_alias", room_alias);
|
||||
|
@ -235,7 +244,7 @@ angular.module('matrixService', [])
|
|||
|
||||
// get a list of public rooms on your home server
|
||||
publicRooms: function() {
|
||||
var path = "/public/rooms"
|
||||
var path = "/publicRooms"
|
||||
return doRequest("GET", path);
|
||||
},
|
||||
|
||||
|
@ -407,6 +416,40 @@ angular.module('matrixService', [])
|
|||
localStorage.setItem("config", JSON.stringify(config));
|
||||
},
|
||||
|
||||
|
||||
/****** Room aliases management ******/
|
||||
|
||||
/**
|
||||
* Enhance data returned by rooms() and publicRooms() by adding room_alias
|
||||
* & room_display_name which are computed from data already retrieved from the server.
|
||||
* @param {Array} data the response of rooms() and publicRooms()
|
||||
* @returns {Array} the same array with enriched objects
|
||||
*/
|
||||
assignRoomAliases: function(data) {
|
||||
for (var i=0; i<data.length; i++) {
|
||||
var alias = this.getRoomIdToAliasMapping(data[i].room_id);
|
||||
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
|
||||
this.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_display_name = data[i].room_id;
|
||||
}
|
||||
}
|
||||
return data;
|
||||
},
|
||||
|
||||
createRoomIdToAliasMapping: function(roomId, alias) {
|
||||
localStorage.setItem(MAPPING_PREFIX+roomId, alias);
|
||||
},
|
||||
|
|
|
@ -16,12 +16,11 @@ limitations under the License.
|
|||
|
||||
'use strict';
|
||||
|
||||
angular.module('HomeController', ['matrixService', 'mFileInput', 'mFileUpload', 'eventHandlerService'])
|
||||
.controller('HomeController', ['$scope', '$location', 'matrixService', 'mFileUpload', 'eventHandlerService', 'eventStreamService',
|
||||
function($scope, $location, matrixService, mFileUpload, eventHandlerService, eventStreamService) {
|
||||
angular.module('HomeController', ['matrixService', 'eventHandlerService', 'RecentsController'])
|
||||
.controller('HomeController', ['$scope', '$location', 'matrixService', 'eventHandlerService', 'eventStreamService',
|
||||
function($scope, $location, matrixService, eventHandlerService, eventStreamService) {
|
||||
|
||||
$scope.config = matrixService.config();
|
||||
$scope.rooms = {};
|
||||
$scope.public_rooms = [];
|
||||
$scope.newRoomId = "";
|
||||
$scope.feedback = "";
|
||||
|
@ -32,72 +31,18 @@ angular.module('HomeController', ['matrixService', 'mFileInput', 'mFileUpload',
|
|||
};
|
||||
|
||||
$scope.goToRoom = {
|
||||
room_id: "",
|
||||
room_id: ""
|
||||
};
|
||||
|
||||
$scope.joinAlias = {
|
||||
room_alias: "",
|
||||
};
|
||||
|
||||
$scope.$on(eventHandlerService.MEMBER_EVENT, function(ngEvent, event, isLive) {
|
||||
var config = matrixService.config();
|
||||
if (event.state_key === config.user_id && event.content.membership === "invite") {
|
||||
console.log("Invited to room " + event.room_id);
|
||||
// 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_display_name = event.user_id + "'s room";
|
||||
$scope.rooms[event.room_id] = event;
|
||||
}
|
||||
});
|
||||
|
||||
var assignRoomAliases = function(data) {
|
||||
for (var i=0; i<data.length; i++) {
|
||||
var alias = matrixService.getRoomIdToAliasMapping(data[i].room_id);
|
||||
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_display_name = data[i].room_id;
|
||||
}
|
||||
}
|
||||
return data;
|
||||
room_alias: ""
|
||||
};
|
||||
|
||||
var refresh = function() {
|
||||
// List all rooms joined or been invited to
|
||||
matrixService.rooms(1,true).then(
|
||||
function(response) {
|
||||
var data = assignRoomAliases(response.data.rooms);
|
||||
$scope.feedback = "Success";
|
||||
for (var i=0; i<data.length; i++) {
|
||||
$scope.rooms[data[i].room_id] = data[i];
|
||||
}
|
||||
|
||||
var presence = response.data.presence;
|
||||
for (var i = 0; i < presence.length; ++i) {
|
||||
eventHandlerService.handleEvent(presence[i], false);
|
||||
}
|
||||
},
|
||||
function(error) {
|
||||
$scope.feedback = "Failure: " + error.data;
|
||||
});
|
||||
|
||||
matrixService.publicRooms().then(
|
||||
function(response) {
|
||||
$scope.public_rooms = assignRoomAliases(response.data.chunk);
|
||||
$scope.public_rooms = matrixService.assignRoomAliases(response.data.chunk);
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
@ -23,13 +23,8 @@
|
|||
</form>
|
||||
</div>
|
||||
|
||||
<h3>My rooms</h3>
|
||||
|
||||
<div class="rooms" ng-repeat="(rm_id, room) in rooms">
|
||||
<div>
|
||||
<a href="#/room/{{ room.room_alias ? room.room_alias : rm_id }}" >{{ room.room_display_name }}</a> {{room.membership === 'invite' ? ' (invited)' : ''}}
|
||||
</div>
|
||||
</div>
|
||||
<h3>Recents</h3>
|
||||
<div ng-include="'recents/recents.html'"></div>
|
||||
<br/>
|
||||
|
||||
<h3>Public rooms</h3>
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
<script src="app-filter.js"></script>
|
||||
<script src="home/home-controller.js"></script>
|
||||
<script src="login/login-controller.js"></script>
|
||||
<script src="recents/recents-controller.js"></script>
|
||||
<script src="recents/recents-filter.js"></script>
|
||||
<script src="room/room-controller.js"></script>
|
||||
<script src="room/room-directive.js"></script>
|
||||
<script src="settings/settings-controller.js"></script>
|
||||
|
@ -37,7 +39,7 @@
|
|||
<header id="header">
|
||||
<!-- Do not show buttons on the login page -->
|
||||
<div id="header-buttons" ng-hide="'/login' == location ">
|
||||
<button ng-click='go("settings")'>Settings</button>
|
||||
<button ng-click='goToPage("settings")'>Settings</button>
|
||||
<button ng-click="logout()">Log out</button>
|
||||
</div>
|
||||
</header>
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
Copyright 2014 matrix.org
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
angular.module('RecentsController', ['matrixService', 'eventHandlerService'])
|
||||
.controller('RecentsController', ['$scope', 'matrixService', 'eventHandlerService', 'eventStreamService',
|
||||
function($scope, matrixService, eventHandlerService, eventStreamService) {
|
||||
$scope.rooms = {};
|
||||
|
||||
$scope.$on(eventHandlerService.MEMBER_EVENT, function(ngEvent, event, isLive) {
|
||||
var config = matrixService.config();
|
||||
if (event.state_key === config.user_id && event.content.membership === "invite") {
|
||||
console.log("Invited to room " + event.room_id);
|
||||
// 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_display_name = event.user_id + "'s room";
|
||||
$scope.rooms[event.room_id] = event;
|
||||
}
|
||||
});
|
||||
|
||||
var refresh = function() {
|
||||
// List all rooms joined or been invited to
|
||||
matrixService.rooms(1, false).then(
|
||||
function(response) {
|
||||
var data = matrixService.assignRoomAliases(response.data.rooms);
|
||||
for (var i=0; i<data.length; i++) {
|
||||
$scope.rooms[data[i].room_id] = data[i];
|
||||
|
||||
// Create a shortcut for the last message of this room
|
||||
if (data[i].messages && data[i].messages.chunk && data[i].messages.chunk[0]) {
|
||||
$scope.rooms[data[i].room_id].lastMsg = data[i].messages.chunk[0];
|
||||
}
|
||||
}
|
||||
|
||||
var presence = response.data.presence;
|
||||
for (var i = 0; i < presence.length; ++i) {
|
||||
eventHandlerService.handleEvent(presence[i], false);
|
||||
}
|
||||
},
|
||||
function(error) {
|
||||
$scope.feedback = "Failure: " + error.data;
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
$scope.onInit = function() {
|
||||
refresh();
|
||||
};
|
||||
|
||||
}]);
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
Copyright 2014 matrix.org
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
angular.module('RecentsController')
|
||||
.filter('orderRecents', function() {
|
||||
return function(rooms) {
|
||||
|
||||
// Transform the dict into an array
|
||||
// The key, room_id, is already in value objects
|
||||
var filtered = [];
|
||||
angular.forEach(rooms, function(value, key) {
|
||||
filtered.push( value );
|
||||
});
|
||||
|
||||
// And time sort them
|
||||
// The room with the lastest message at first
|
||||
filtered.sort(function (a, b) {
|
||||
// Invite message does not have a body message nor ts
|
||||
// Puth them at the top of the list
|
||||
if (undefined === a.lastMsg) {
|
||||
return -1;
|
||||
}
|
||||
else if (undefined === b.lastMsg) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return b.lastMsg.ts - a.lastMsg.ts;
|
||||
}
|
||||
});
|
||||
return filtered;
|
||||
};
|
||||
});
|
|
@ -0,0 +1,53 @@
|
|||
<div ng-controller="RecentsController" data-ng-init="onInit()">
|
||||
<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" >
|
||||
<tr>
|
||||
<td class="recentsRoomName">
|
||||
{{ room.room_display_name }}
|
||||
</td>
|
||||
<td class="recentsRoomSummaryTS">
|
||||
{{ (room.lastMsg.ts) | date:'MMM d HH:mm' }}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td colspan="2" class="recentsRoomSummary">
|
||||
|
||||
<div ng-show="room.membership === 'invite'" >
|
||||
{{ room.inviter }} invited you
|
||||
</div>
|
||||
|
||||
<div ng-hide="room.membership === 'invite'" ng-switch="room.lastMsg.type" >
|
||||
<div ng-switch-when="m.room.member">
|
||||
{{ room.lastMsg.user_id }}
|
||||
{{ {"join": "joined", "leave": "left", "invite": "invited"}[room.lastMsg.content.membership] }}
|
||||
{{ room.lastMsg.content.membership === "invite" ? (room.lastMsg.state_key || '') : '' }}
|
||||
</div>
|
||||
|
||||
<div ng-switch-when="m.room.message">
|
||||
<div ng-switch="room.lastMsg.content.msgtype">
|
||||
<div ng-switch-when="m.text">
|
||||
{{ room.lastMsg.user_id }} :
|
||||
<span ng-bind-html="(room.lastMsg.content.body) | linky:'_blank'">
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div ng-switch-when="m.image">
|
||||
{{ room.lastMsg.user_id }} sent an image
|
||||
</div>
|
||||
|
||||
<div ng-switch-default>
|
||||
{{ room.lastMsg.content }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-switch-default>
|
||||
{{ room.lastMsg }}
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
Loading…
Reference in New Issue