diff options
-rw-r--r-- | webclient/components/matrix/event-handler-service.js | 83 | ||||
-rw-r--r-- | webclient/recents/recents-controller.js | 130 | ||||
-rw-r--r-- | webclient/recents/recents-filter.js | 33 | ||||
-rw-r--r-- | webclient/recents/recents.html | 66 |
4 files changed, 141 insertions, 171 deletions
diff --git a/webclient/components/matrix/event-handler-service.js b/webclient/components/matrix/event-handler-service.js index 4604ff6192..4b0566fe33 100644 --- a/webclient/components/matrix/event-handler-service.js +++ b/webclient/components/matrix/event-handler-service.js @@ -63,13 +63,14 @@ angular.module('eventHandlerService', []) var initRoom = function(room_id) { if (!(room_id in $rootScope.events.rooms)) { console.log("Creating new handler entry for " + room_id); - $rootScope.events.rooms[room_id] = {}; - $rootScope.events.rooms[room_id].messages = []; - $rootScope.events.rooms[room_id].members = {}; - - // Pagination information - $rootScope.events.rooms[room_id].pagination = { - earliest_token: "END" // how far back we've paginated + $rootScope.events.rooms[room_id] = { + room_id: room_id, + messages: [], + members: {}, + // Pagination information + pagination: { + earliest_token: "END" // how far back we've paginated + } }; } }; @@ -257,7 +258,9 @@ angular.module('eventHandlerService', []) // FIXME: /initialSync on a particular room is not yet available // So initRoom on a new room is not called. Make sure the room data is initialised here - initRoom(event.room_id); + if (event.room_id) { + initRoom(event.room_id); + } // Avoid duplicated events // Needed for rooms where initialSync has not been done. @@ -347,6 +350,70 @@ angular.module('eventHandlerService', []) resetRoomMessages: function(room_id) { resetRoomMessages(room_id); + }, + + /** + * Return the last message event of a room + * @param {String} room_id the room id + * @param {Boolean} filterFake true to not take into account fake messages + * @returns {undefined | Event} the last message event if available + */ + getLastMessage: function(room_id, filterEcho) { + var lastMessage; + + var room = $rootScope.events.rooms[room_id]; + if (room) { + for (var i = room.messages.length - 1; i >= 0; i--) { + var message = room.messages[i]; + + if (!filterEcho || undefined === message.echo_msg_state) { + lastMessage = message; + break; + } + } + } + + return lastMessage; + }, + + /** + * Compute the room users number, ie the number of members who has joined the room. + * @param {String} room_id the room id + * @returns {undefined | Number} the room users number if available + */ + getUsersCountInRoom: function(room_id) { + var memberCount; + + var room = $rootScope.events.rooms[room_id]; + if (room) { + memberCount = 0; + + for (var i in room.members) { + var member = room.members[i]; + + if ("join" === member.membership) { + memberCount = memberCount + 1; + } + } + } + + return memberCount; + }, + + /** + * Get the member object of a room member + * @param {String} room_id the room id + * @param {String} user_id the id of the user + * @returns {undefined | Object} the member object of this user in this room if he is part of the room + */ + getMember: function(room_id, user_id) { + var member; + + var room = $rootScope.events.rooms[room_id]; + if (room) { + member = room.members[user_id]; + } + return member; } }; }]); diff --git a/webclient/recents/recents-controller.js b/webclient/recents/recents-controller.js index a0db0538f3..ee8a41c366 100644 --- a/webclient/recents/recents-controller.js +++ b/webclient/recents/recents-controller.js @@ -16,134 +16,16 @@ 'use strict'; -angular.module('RecentsController', ['matrixService', 'matrixFilter', 'eventHandlerService']) -.controller('RecentsController', ['$rootScope', '$scope', 'matrixService', 'eventHandlerService', - function($rootScope, $scope, matrixService, eventHandlerService) { - - // FIXME: Angularjs reloads the controller (and resets its $scope) each time - // the page URL changes, use $rootScope to avoid to have to reload data - $rootScope.rooms; +angular.module('RecentsController', ['matrixService', 'matrixFilter']) +.controller('RecentsController', ['$rootScope', '$scope', 'eventHandlerService', + function($rootScope, $scope, eventHandlerService) { + + // Expose the service to the view + $scope.eventHandlerService = eventHandlerService; // $rootScope of the parent where the recents component is included can override this value // in order to highlight a specific room in the list $rootScope.recentsSelectedRoomID; - - var listenToEventStream = function() { - // Refresh the list on matrix invitation and message event - $rootScope.$on(eventHandlerService.MEMBER_EVENT, function(ngEvent, event, isLive) { - if (isLive) { - if (!$rootScope.rooms[event.room_id]) { - // The user has joined a new room, which we do not have data yet. The reason is that - // the room has appeared in the scope of the user rooms after the global initialSync - // FIXME: an initialSync on this specific room should be done - $rootScope.rooms[event.room_id] = { - room_id:event.room_id - }; - } - else if (event.state_key === matrixService.config().user_id && "invite" !== event.membership && "join" !== event.membership) { - // The user has been kicked or banned from the room, remove this room from the recents - delete $rootScope.rooms[event.room_id]; - } - - if ($rootScope.rooms[event.room_id]) { - $rootScope.rooms[event.room_id].lastMsg = event; - } - - // Update room users count - $rootScope.rooms[event.room_id].numUsersInRoom = getUsersCountInRoom(event.room_id); - } - }); - $rootScope.$on(eventHandlerService.MSG_EVENT, function(ngEvent, event, isLive) { - if (isLive) { - $rootScope.rooms[event.room_id].lastMsg = event; - } - }); - $rootScope.$on(eventHandlerService.CALL_EVENT, function(ngEvent, event, isLive) { - if (isLive) { - $rootScope.rooms[event.room_id].lastMsg = event; - } - }); - $rootScope.$on(eventHandlerService.ROOM_CREATE_EVENT, function(ngEvent, event, isLive) { - if (isLive) { - $rootScope.rooms[event.room_id] = event; - } - }); - $rootScope.$on(eventHandlerService.NAME_EVENT, function(ngEvent, event, isLive) { - if (isLive) { - $rootScope.rooms[event.room_id].lastMsg = event; - } - }); - $rootScope.$on(eventHandlerService.TOPIC_EVENT, function(ngEvent, event, isLive) { - if (isLive) { - $rootScope.rooms[event.room_id].lastMsg = event; - } - }); - }; - - /** - * Compute the room users number, ie the number of members who has joined the room. - * @param {String} room_id the room id - * @returns {undefined | Number} the room users number if available - */ - var getUsersCountInRoom = function(room_id) { - var memberCount; - - var room = $rootScope.events.rooms[room_id]; - if (room) { - memberCount = 0; - - for (var i in room.members) { - var member = room.members[i]; - - if ("join" === member.membership) { - memberCount = memberCount + 1; - } - } - } - - return memberCount; - }; - - $scope.onInit = function() { - // Init recents list only once - if ($rootScope.rooms) { - return; - } - - $rootScope.rooms = {}; - - // Use initialSync data to init the recents list - eventHandlerService.waitForInitialSyncCompletion().then( - function(initialSyncData) { - - var rooms = initialSyncData.data.rooms; - for (var i=0; i<rooms.length; i++) { - var room = rooms[i]; - - // Add room_alias & room_display_name members - $rootScope.rooms[room.room_id] = angular.extend(room, matrixService.getRoomAliasAndDisplayName(room)); - - // Create a shortcut for the last message of this room - if (room.messages && room.messages.chunk && room.messages.chunk[0]) { - $rootScope.rooms[room.room_id].lastMsg = room.messages.chunk[0]; - } - - $rootScope.rooms[room.room_id].numUsersInRoom = getUsersCountInRoom(room.room_id); - } - - // From now, update recents from the stream - listenToEventStream(); - }, - function(error) { - $rootScope.feedback = "Failure: " + error.data; - } - ); - }; - - // Clean data when user logs out - $scope.$on(eventHandlerService.RESET_EVENT, function() { - delete $rootScope.rooms; - }); }]); diff --git a/webclient/recents/recents-filter.js b/webclient/recents/recents-filter.js index d80de6fbeb..2fd4dbe98b 100644 --- a/webclient/recents/recents-filter.js +++ b/webclient/recents/recents-filter.js @@ -17,31 +17,48 @@ 'use strict'; angular.module('RecentsController') -.filter('orderRecents', function() { +.filter('orderRecents', ["matrixService", "eventHandlerService", function(matrixService, eventHandlerService) { return function(rooms) { + var user_id = matrixService.config().user_id; + // 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 ); + angular.forEach(rooms, function(room, room_id) { + + // Show the room only if the user has joined it or has been invited + // (ie, do not show it if he has been banned) + var member = eventHandlerService.getMember(room_id, user_id); + if (member && ("invite" === member.membership || "join" === member.membership)) { + + // Count users here + // TODO: Compute it directly in eventHandlerService + room.numUsersInRoom = eventHandlerService.getUsersCountInRoom(room_id); + + filtered.push(room); + } }); // And time sort them // The room with the lastest message at first - filtered.sort(function (a, b) { + filtered.sort(function (roomA, roomB) { + + var lastMsgRoomA = eventHandlerService.getLastMessage(roomA.room_id, true); + var lastMsgRoomB = eventHandlerService.getLastMessage(roomB.room_id, true); + // Invite message does not have a body message nor ts // Puth them at the top of the list - if (undefined === a.lastMsg) { + if (undefined === lastMsgRoomA) { return -1; } - else if (undefined === b.lastMsg) { + else if (undefined === lastMsgRoomB) { return 1; } else { - return b.lastMsg.ts - a.lastMsg.ts; + return lastMsgRoomB.ts - lastMsgRoomA.ts; } }); return filtered; }; -}); \ No newline at end of file +}]); \ No newline at end of file diff --git a/webclient/recents/recents.html b/webclient/recents/recents.html index ca7636e36a..789ffc9d20 100644 --- a/webclient/recents/recents.html +++ b/webclient/recents/recents.html @@ -1,9 +1,9 @@ -<div ng-controller="RecentsController" data-ng-init="onInit()"> +<div ng-controller="RecentsController"> <table class="recentsTable"> - <tbody ng-repeat="(rm_id, room) in rooms | orderRecents" + <tbody ng-repeat="(index, room) in events.rooms | orderRecents" ng-click="goToPage('room/' + (room.room_alias ? room.room_alias : room.room_id) )" class ="recentsRoom" - ng-class="{'recentsRoomSelected': (room.room_id === recentsSelectedRoomID)}"> + ng-class="{'recentsRoomSelected': (room.room_id === recentsSelectedRoomID)}"> <tr> <td class="recentsRoomName"> {{ room.room_id | mRoomName }} @@ -14,7 +14,11 @@ </span> </td> <td class="recentsRoomSummaryTS"> - {{ (room.lastMsg.ts) | date:'MMM d HH:mm' }} + <!-- Use a temp var as alias to the last room message. + Declaring it in this way ensures the data-binding --> + {{ lastMsg = eventHandlerService.getLastMessage(room.room_id, true);"" }} + + {{ (lastMsg.ts) | date:'MMM d HH:mm' }} </td> </tr> @@ -25,67 +29,67 @@ {{ room.inviter | mUserDisplayName: room.room_id }} invited you </div> - <div ng-hide="room.membership === 'invite'" ng-switch="room.lastMsg.type"> + <div ng-hide="room.membership === 'invite'" ng-switch="lastMsg.type"> <div ng-switch-when="m.room.member"> - <span ng-if="'join' === room.lastMsg.content.membership"> - {{ room.lastMsg.state_key | mUserDisplayName: room.room_id}} joined + <span ng-if="'join' === lastMsg.content.membership"> + {{ lastMsg.state_key | mUserDisplayName: room.room_id}} joined </span> - <span ng-if="'leave' === room.lastMsg.content.membership"> - <span ng-if="room.lastMsg.user_id === room.lastMsg.state_key"> - {{room.lastMsg.state_key | mUserDisplayName: room.room_id }} left + <span ng-if="'leave' === lastMsg.content.membership"> + <span ng-if="lastMsg.user_id === lastMsg.state_key"> + {{lastMsg.state_key | mUserDisplayName: room.room_id }} left </span> - <span ng-if="room.lastMsg.user_id !== room.lastMsg.state_key"> - {{ room.lastMsg.user_id | mUserDisplayName: room.room_id }} - {{ {"join": "kicked", "ban": "unbanned"}[room.lastMsg.content.prev] }} - {{ room.lastMsg.state_key | mUserDisplayName: room.room_id }} + <span ng-if="lastMsg.user_id !== lastMsg.state_key"> + {{ lastMsg.user_id | mUserDisplayName: room.room_id }} + {{ {"join": "kicked", "ban": "unbanned"}[lastMsg.content.prev] }} + {{ lastMsg.state_key | mUserDisplayName: room.room_id }} </span> - <span ng-if="'join' === room.lastMsg.content.prev && room.lastMsg.content.reason"> - : {{ room.lastMsg.content.reason }} + <span ng-if="'join' === lastMsg.content.prev && lastMsg.content.reason"> + : {{ lastMsg.content.reason }} </span> </span> - <span ng-if="'invite' === room.lastMsg.content.membership || 'ban' === room.lastMsg.content.membership"> - {{ room.lastMsg.user_id | mUserDisplayName: room.room_id }} - {{ {"invite": "invited", "ban": "banned"}[room.lastMsg.content.membership] }} - {{ room.lastMsg.state_key | mUserDisplayName: room.room_id }} - <span ng-if="'ban' === room.lastMsg.content.prev && room.lastMsg.content.reason"> - : {{ room.lastMsg.content.reason }} + <span ng-if="'invite' === lastMsg.content.membership || 'ban' === lastMsg.content.membership"> + {{ lastMsg.user_id | mUserDisplayName: room.room_id }} + {{ {"invite": "invited", "ban": "banned"}[lastMsg.content.membership] }} + {{ lastMsg.state_key | mUserDisplayName: room.room_id }} + <span ng-if="'ban' === lastMsg.content.prev && lastMsg.content.reason"> + : {{ lastMsg.content.reason }} </span> </span> </div> <div ng-switch-when="m.room.message"> - <div ng-switch="room.lastMsg.content.msgtype"> + <div ng-switch="lastMsg.content.msgtype"> <div ng-switch-when="m.text"> - {{ room.lastMsg.user_id | mUserDisplayName: room.room_id }} : - <span ng-bind-html="(room.lastMsg.content.body) | linky:'_blank'"> + {{ lastMsg.user_id | mUserDisplayName: room.room_id }} : + <span ng-bind-html="(lastMsg.content.body) | linky:'_blank'"> </span> </div> <div ng-switch-when="m.image"> - {{ room.lastMsg.user_id | mUserDisplayName: room.room_id }} sent an image + {{ lastMsg.user_id | mUserDisplayName: room.room_id }} sent an image </div> <div ng-switch-when="m.emote"> - <span ng-bind-html="'* ' + (room.lastMsg.user_id | mUserDisplayName: room.room_id) + ' ' + room.lastMsg.content.body | linky:'_blank'"> + <span ng-bind-html="'* ' + (lastMsg.user_id | mUserDisplayName: room.room_id) + ' ' + lastMsg.content.body | linky:'_blank'"> </span> </div> <div ng-switch-default> - {{ room.lastMsg.content }} + {{ lastMsg.content }} </div> </div> </div> <div ng-switch-when="m.room.topic"> - {{ room.lastMsg.user_id | mUserDisplayName: room.room_id }} changed the topic to: {{ room.lastMsg.content.topic }} + {{ lastMsg.user_id | mUserDisplayName: room.room_id }} changed the topic to: {{ lastMsg.content.topic }} </div> <div ng-switch-when="m.room.name"> - {{ room.lastMsg.user_id | mUserDisplayName: room.room_id }} changed the room name to: {{ room.lastMsg.content.name }} + {{ lastMsg.user_id | mUserDisplayName: room.room_id }} changed the room name to: {{ lastMsg.content.name }} </div> <div ng-switch-default> - <div ng-if="room.lastMsg.type.indexOf('m.call.') === 0"> + <div ng-if="lastMsg.type.indexOf('m.call.') === 0"> Call </div> </div> |