mirror of
https://github.com/element-hq/synapse
synced 2024-09-11 01:55:11 +00:00
Merge branch 'develop' of github.com:matrix-org/synapse into stream_refactor
This commit is contained in:
commit
08881d808d
14 changed files with 289 additions and 111 deletions
|
@ -15,8 +15,7 @@
|
||||||
|
|
||||||
|
|
||||||
from . import (
|
from . import (
|
||||||
room, events, register, login, profile, public, presence, initial_sync,
|
room, events, register, login, profile, presence, initial_sync, directory
|
||||||
directory
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,7 +39,6 @@ class RestServletFactory(object):
|
||||||
register.register_servlets(hs, client_resource)
|
register.register_servlets(hs, client_resource)
|
||||||
login.register_servlets(hs, client_resource)
|
login.register_servlets(hs, client_resource)
|
||||||
profile.register_servlets(hs, client_resource)
|
profile.register_servlets(hs, client_resource)
|
||||||
public.register_servlets(hs, client_resource)
|
|
||||||
presence.register_servlets(hs, client_resource)
|
presence.register_servlets(hs, client_resource)
|
||||||
initial_sync.register_servlets(hs, client_resource)
|
initial_sync.register_servlets(hs, client_resource)
|
||||||
directory.register_servlets(hs, client_resource)
|
directory.register_servlets(hs, client_resource)
|
||||||
|
|
|
@ -31,7 +31,7 @@ def register_servlets(hs, http_server):
|
||||||
|
|
||||||
|
|
||||||
class ClientDirectoryServer(RestServlet):
|
class ClientDirectoryServer(RestServlet):
|
||||||
PATTERN = client_path_pattern("/ds/room/(?P<room_alias>[^/]*)$")
|
PATTERN = client_path_pattern("/directory/room/(?P<room_alias>[^/]*)$")
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def on_GET(self, request, room_alias):
|
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)
|
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
|
# TODO: Needs unit testing
|
||||||
class RoomMemberListRestServlet(RestServlet):
|
class RoomMemberListRestServlet(RestServlet):
|
||||||
PATTERN = client_path_pattern("/rooms/(?P<room_id>[^/]*)/members$")
|
PATTERN = client_path_pattern("/rooms/(?P<room_id>[^/]*)/members$")
|
||||||
|
@ -424,3 +435,4 @@ def register_servlets(hs, http_server):
|
||||||
RoomTriggerBackfill(hs).register(http_server)
|
RoomTriggerBackfill(hs).register(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)
|
||||||
|
|
|
@ -37,7 +37,11 @@ angular.module('MatrixWebClientController', ['matrixService', 'mPresence', 'even
|
||||||
mPresence.start();
|
mPresence.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.go = function(url) {
|
/**
|
||||||
|
* Open a given page.
|
||||||
|
* @param {String} url url of the page
|
||||||
|
*/
|
||||||
|
$scope.goToPage = function(url) {
|
||||||
$location.url(url);
|
$location.url(url);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -342,6 +342,51 @@ h1 {
|
||||||
top: 0;
|
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 ***/
|
||||||
|
|
||||||
.profile-avatar {
|
.profile-avatar {
|
||||||
|
|
|
@ -20,6 +20,7 @@ var matrixWebClient = angular.module('matrixWebClient', [
|
||||||
'LoginController',
|
'LoginController',
|
||||||
'RoomController',
|
'RoomController',
|
||||||
'HomeController',
|
'HomeController',
|
||||||
|
'RecentsController',
|
||||||
'SettingsController',
|
'SettingsController',
|
||||||
'UserController',
|
'UserController',
|
||||||
'matrixService',
|
'matrixService',
|
||||||
|
|
|
@ -106,11 +106,20 @@ angular.module('matrixService', [])
|
||||||
},
|
},
|
||||||
|
|
||||||
// List all rooms joined or been invited to
|
// List all rooms joined or been invited to
|
||||||
rooms: function(from, to, limit) {
|
rooms: function(limit, feedback) {
|
||||||
// The REST path spec
|
// The REST path spec
|
||||||
|
|
||||||
var path = "/initialSync";
|
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
|
// Joins a room
|
||||||
|
@ -155,7 +164,7 @@ angular.module('matrixService', [])
|
||||||
|
|
||||||
// Retrieves the room ID corresponding to a room alias
|
// Retrieves the room ID corresponding to a room alias
|
||||||
resolveRoomAlias:function(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);
|
room_alias = encodeURIComponent(room_alias);
|
||||||
|
|
||||||
path = path.replace("$room_alias", 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
|
// get a list of public rooms on your home server
|
||||||
publicRooms: function() {
|
publicRooms: function() {
|
||||||
var path = "/public/rooms"
|
var path = "/publicRooms"
|
||||||
return doRequest("GET", path);
|
return doRequest("GET", path);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -406,6 +415,40 @@ angular.module('matrixService', [])
|
||||||
config.version = configVersion;
|
config.version = configVersion;
|
||||||
localStorage.setItem("config", JSON.stringify(config));
|
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) {
|
createRoomIdToAliasMapping: function(roomId, alias) {
|
||||||
localStorage.setItem(MAPPING_PREFIX+roomId, alias);
|
localStorage.setItem(MAPPING_PREFIX+roomId, alias);
|
||||||
|
|
|
@ -16,12 +16,11 @@ limitations under the License.
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('HomeController', ['matrixService', 'mFileInput', 'mFileUpload', 'eventHandlerService'])
|
angular.module('HomeController', ['matrixService', 'eventHandlerService', 'RecentsController'])
|
||||||
.controller('HomeController', ['$scope', '$location', 'matrixService', 'mFileUpload', 'eventHandlerService', 'eventStreamService',
|
.controller('HomeController', ['$scope', '$location', 'matrixService', 'eventHandlerService', 'eventStreamService',
|
||||||
function($scope, $location, matrixService, mFileUpload, eventHandlerService, eventStreamService) {
|
function($scope, $location, matrixService, eventHandlerService, eventStreamService) {
|
||||||
|
|
||||||
$scope.config = matrixService.config();
|
$scope.config = matrixService.config();
|
||||||
$scope.rooms = {};
|
|
||||||
$scope.public_rooms = [];
|
$scope.public_rooms = [];
|
||||||
$scope.newRoomId = "";
|
$scope.newRoomId = "";
|
||||||
$scope.feedback = "";
|
$scope.feedback = "";
|
||||||
|
@ -32,72 +31,18 @@ angular.module('HomeController', ['matrixService', 'mFileInput', 'mFileUpload',
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.goToRoom = {
|
$scope.goToRoom = {
|
||||||
room_id: "",
|
room_id: ""
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.joinAlias = {
|
$scope.joinAlias = {
|
||||||
room_alias: "",
|
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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var refresh = function() {
|
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(
|
matrixService.publicRooms().then(
|
||||||
function(response) {
|
function(response) {
|
||||||
$scope.public_rooms = assignRoomAliases(response.data.chunk);
|
$scope.public_rooms = matrixService.assignRoomAliases(response.data.chunk);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -23,13 +23,8 @@
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h3>My rooms</h3>
|
<h3>Recents</h3>
|
||||||
|
<div ng-include="'recents/recents.html'"></div>
|
||||||
<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>
|
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
<h3>Public rooms</h3>
|
<h3>Public rooms</h3>
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
<script src="app-filter.js"></script>
|
<script src="app-filter.js"></script>
|
||||||
<script src="home/home-controller.js"></script>
|
<script src="home/home-controller.js"></script>
|
||||||
<script src="login/login-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-controller.js"></script>
|
||||||
<script src="room/room-directive.js"></script>
|
<script src="room/room-directive.js"></script>
|
||||||
<script src="settings/settings-controller.js"></script>
|
<script src="settings/settings-controller.js"></script>
|
||||||
|
@ -37,7 +39,7 @@
|
||||||
<header id="header">
|
<header id="header">
|
||||||
<!-- Do not show buttons on the login page -->
|
<!-- Do not show buttons on the login page -->
|
||||||
<div id="header-buttons" ng-hide="'/login' == location ">
|
<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>
|
<button ng-click="logout()">Log out</button>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
66
webclient/recents/recents-controller.js
Normal file
66
webclient/recents/recents-controller.js
Normal file
|
@ -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();
|
||||||
|
};
|
||||||
|
|
||||||
|
}]);
|
||||||
|
|
47
webclient/recents/recents-filter.js
Normal file
47
webclient/recents/recents-filter.js
Normal file
|
@ -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;
|
||||||
|
};
|
||||||
|
});
|
53
webclient/recents/recents.html
Normal file
53
webclient/recents/recents.html
Normal file
|
@ -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 a new issue