diff --git a/webclient/app.css b/webclient/app.css index 425d5bb11a..9a4666ad7b 100755 --- a/webclient/app.css +++ b/webclient/app.css @@ -417,6 +417,13 @@ a:active { color: #000; } text-align: left ! important; } +.bubble .messagePending { + opacity: 0.3 +} +.messageUnSent { + color: #F00; +} + #room-fullscreen-image { position: absolute; top: 0px; diff --git a/webclient/room/room-controller.js b/webclient/room/room-controller.js index 07e3695b69..b9ba23dc48 100644 --- a/webclient/room/room-controller.js +++ b/webclient/room/room-controller.js @@ -32,7 +32,7 @@ angular.module('RoomController', ['ngSanitize', 'matrixFilter', 'mFileInput']) first_pagination: true, // this is toggled off when the first pagination is done can_paginate: true, // this is toggled off when we run out of items paginating: false, // used to avoid concurrent pagination requests pulling in dup contents - stream_failure: undefined, // the response when the stream fails + stream_failure: undefined // the response when the stream fails }; $scope.members = {}; $scope.autoCompleting = false; @@ -395,17 +395,55 @@ angular.module('RoomController', ['ngSanitize', 'matrixFilter', 'mFileInput']) // By default send this as a message unless it's an IRC-style command if (!promise && !isCmd) { - promise = matrixService.sendTextMessage($scope.room_id, $scope.textInput); + var message = $scope.textInput; + $scope.textInput = ""; + + // Echo the message to the room + // To do so, create a minimalist fake text message event and add it to the in-memory list of room messages + var echoMessage = { + content: { + body: message, + hsob_ts: "Sending...", // Hack timestamp to display this text in place of the message time + 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 + }; + + $rootScope.events.rooms[$scope.room_id].messages.push(echoMessage); + scrollToBottom(); + + // Make the request + promise = matrixService.sendTextMessage($scope.room_id, message); } if (promise) { 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); + } + } + else { + $scope.textInput = ""; + } }, function(error) { $scope.feedback = "Request failed: " + error.data.error; + + if (echoMessage) { + // Mark the message as unsent for the rest of the page life + echoMessage.content.hsob_ts = "Unsent"; + echoMessage.echo_msg_state = "messageUnSent"; + } }); } }; diff --git a/webclient/room/room.html b/webclient/room/room.html index 493884f601..147113987e 100644 --- a/webclient/room/room.html +++ b/webclient/room/room.html @@ -40,7 +40,10 @@ ng-class="(events.rooms[room_id].messages[$index + 1].user_id !== msg.user_id ? 'differentUser' : '') + (msg.user_id === state.user_id ? ' mine' : '')" scroll-item>
{{ members[msg.user_id].displayname || msg.user_id }}
-
{{ (msg.content.hsob_ts || msg.ts) | date:'MMM d HH:mm' }}
+
+ {{ (msg.content.hsob_ts || msg.ts) | date:'MMM d HH:mm' }} +
- +