From a1bf28b7f0c01f5765e86ca427a1aaaf984842b2 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Sat, 6 Sep 2014 00:31:57 -0700 Subject: [PATCH] handle m.room.aliases for id<->alias mapping; remove local_storage map; stop local echo flickering by removing opacity transition for now; implement /join --- .../matrix/event-handler-service.js | 23 +++++++- .../components/matrix/event-stream-service.js | 1 + webclient/components/matrix/matrix-service.js | 19 ++++++- webclient/room/room-controller.js | 52 ++++++++++++++++--- 4 files changed, 85 insertions(+), 10 deletions(-) diff --git a/webclient/components/matrix/event-handler-service.js b/webclient/components/matrix/event-handler-service.js index ee478d2eb..9732aedfd 100644 --- a/webclient/components/matrix/event-handler-service.js +++ b/webclient/components/matrix/event-handler-service.js @@ -66,11 +66,21 @@ angular.module('eventHandlerService', []) $rootScope.$broadcast(ROOM_CREATE_EVENT, event, isLiveEvent); }; + var handleRoomAliases = function(event, isLiveEvent) { + matrixService.createRoomIdToAliasMapping(event.room_id, event.content.aliases[0]); + }; + var handleMessage = function(event, isLiveEvent) { initRoom(event.room_id); if (isLiveEvent) { - $rootScope.events.rooms[event.room_id].messages.push(event); + if (event.user_id === matrixService.config().user_id) { + // assume we've already echoed it + // FIXME: track events by ID and ungrey the right message to show it's been delivered + } + else { + $rootScope.events.rooms[event.room_id].messages.push(event); + } } else { $rootScope.events.rooms[event.room_id].messages.unshift(event); @@ -87,6 +97,14 @@ angular.module('eventHandlerService', []) var handleRoomMember = function(event, isLiveEvent) { initRoom(event.room_id); + // if the server is stupidly re-relaying a no-op join, discard it. + if (event.prev_content && + event.content.membership === "join" && + event.content.membership === event.prev_content.membership) + { + return; + } + // add membership changes as if they were a room message if something interesting changed if (event.content.prev !== event.content.membership) { if (isLiveEvent) { @@ -144,6 +162,9 @@ angular.module('eventHandlerService', []) case "m.room.create": handleRoomCreate(event, isLiveEvent); break; + case "m.room.aliases": + handleRoomAliases(event, isLiveEvent); + break; case "m.room.message": handleMessage(event, isLiveEvent); break; diff --git a/webclient/components/matrix/event-stream-service.js b/webclient/components/matrix/event-stream-service.js index 1c0f7712b..ed4f3b2ff 100644 --- a/webclient/components/matrix/event-stream-service.js +++ b/webclient/components/matrix/event-stream-service.js @@ -110,6 +110,7 @@ angular.module('eventStreamService', []) var rooms = response.data.rooms; for (var i = 0; i < rooms.length; ++i) { var room = rooms[i]; + // console.log("got room: " + room.room_id); if ("state" in room) { eventHandlerService.handleEvents(room.state, false); } diff --git a/webclient/components/matrix/matrix-service.js b/webclient/components/matrix/matrix-service.js index b7e03657f..a1b9691f0 100644 --- a/webclient/components/matrix/matrix-service.js +++ b/webclient/components/matrix/matrix-service.js @@ -36,6 +36,9 @@ angular.module('matrixService', []) */ var config; + var roomIdToAlias = {}; + var aliasToRoomId = {}; + // Current version of permanent storage var configVersion = 0; var prefixPath = "/_matrix/client/api/v1"; @@ -529,6 +532,8 @@ angular.module('matrixService', []) result.room_alias = alias; result.room_display_name = alias; } + // XXX: this only lets us learn aliases from our local HS - we should + // make the client stop returning this if we can trust m.room.aliases state events else if (room.aliases && room.aliases[0]) { // save the mapping // TODO: select the smarter alias from the array @@ -546,13 +551,23 @@ angular.module('matrixService', []) }, createRoomIdToAliasMapping: function(roomId, alias) { - localStorage.setItem(MAPPING_PREFIX+roomId, alias); + //console.log("creating mapping between " + roomId + " and " + alias); + roomIdToAlias[roomId] = alias; + aliasToRoomId[alias] = roomId; + // localStorage.setItem(MAPPING_PREFIX+roomId, alias); }, getRoomIdToAliasMapping: function(roomId) { - return localStorage.getItem(MAPPING_PREFIX+roomId); + var alias = roomIdToAlias[roomId]; // was localStorage.getItem(MAPPING_PREFIX+roomId) + //console.log("looking for alias for " + roomId + "; found: " + alias); + return alias; }, + getAliasToRoomIdMapping: function(alias) { + var roomId = aliasToRoomId[alias]; + //console.log("looking for roomId for " + alias + "; found: " + roomId); + return roomId; + }, /****** Power levels management ******/ diff --git a/webclient/room/room-controller.js b/webclient/room/room-controller.js index 8203b6ed3..c738b490e 100644 --- a/webclient/room/room-controller.js +++ b/webclient/room/room-controller.js @@ -333,6 +333,40 @@ angular.module('RoomController', ['ngSanitize', 'matrixFilter', 'mFileInput']) $scope.feedback = "Usage: /nick "; } break; + + case "/join": + // Join a room + if (args) { + var matches = args.match(/^(\S+)$/); + if (matches) { + var room_alias = matches[1]; + if (room_alias.indexOf(':') == -1) { + // FIXME: actually track the :domain style name of our homeserver + // with or without port as is appropriate and append it at this point + } + + var room_id = matrixService.getAliasToRoomIdMapping(room_alias); + console.log("joining " + room_alias + " id=" + room_id); + if ($rootScope.events.rooms[room_id]) { + // don't send a join event for a room you're already in. + $location.url("room/" + room_alias); + } + else { + promise = matrixService.joinAlias(room_alias).then( + function(response) { + $location.url("room/" + room_alias); + }, + function(error) { + $scope.feedback = "Can't join room: " + JSON.stringify(error.data); + } + ); + } + } + } + else { + $scope.feedback = "Usage: /join "; + } + break; case "/kick": // Kick a user from the room with an optional reason @@ -428,13 +462,14 @@ angular.module('RoomController', ['ngSanitize', 'matrixFilter', 'mFileInput']) var echoMessage = { content: { body: message, - hsob_ts: "Sending...", // Hack timestamp to display this text in place of the message time + hsob_ts: new Date().getTime(), // fake a timestamp msgtype: "m.text" }, room_id: $scope.room_id, type: "m.room.message", user_id: $scope.state.user_id, - echo_msg_state: "messagePending" // Add custom field to indicate the state of this fake message to HTML + // FIXME: re-enable echo_msg_state when we have a nice way to turn the field off again + // echo_msg_state: "messagePending" // Add custom field to indicate the state of this fake message to HTML }; $rootScope.events.rooms[$scope.room_id].messages.push(echoMessage); @@ -448,18 +483,21 @@ angular.module('RoomController', ['ngSanitize', 'matrixFilter', 'mFileInput']) promise.then( function() { console.log("Request successfully sent"); - + $scope.textInput = ""; +/* if (echoMessage) { // Remove the fake echo message from the room messages // It will be replaced by the one acknowledged by the server - var index = $rootScope.events.rooms[$scope.room_id].messages.indexOf(echoMessage); - if (index > -1) { - $rootScope.events.rooms[$scope.room_id].messages.splice(index, 1); - } + // ...except this causes a nasty flicker. So don't swap messages for now. --matthew + // var index = $rootScope.events.rooms[$scope.room_id].messages.indexOf(echoMessage); + // if (index > -1) { + // $rootScope.events.rooms[$scope.room_id].messages.splice(index, 1); + // } } else { $scope.textInput = ""; } +*/ }, function(error) { $scope.feedback = "Request failed: " + error.data.error;