summary refs log tree commit diff
diff options
context:
space:
mode:
-rwxr-xr-xwebclient/app.css7
-rw-r--r--webclient/room/room-controller.js44
-rw-r--r--webclient/room/room.html9
3 files changed, 55 insertions, 5 deletions
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>
                 <td class="leftBlock">
                     <div class="sender" ng-hide="events.rooms[room_id].messages[$index - 1].user_id === msg.user_id">{{ members[msg.user_id].displayname || msg.user_id }}</div>
-                    <div class="timestamp">{{ (msg.content.hsob_ts || msg.ts) | date:'MMM d HH:mm' }}</div>
+                    <div class="timestamp"
+                         ng-class="msg.echo_msg_state">
+                        {{ (msg.content.hsob_ts || msg.ts) | date:'MMM d HH:mm' }}
+                    </div>
                 </td>
                 <td class="avatar">
                     <img class="avatarImage" ng-src="{{ members[msg.user_id].avatar_url || 'img/default-profile.png' }}" width="32" height="32"
@@ -67,7 +70,9 @@
                             {{ members[msg.state_key].displayname || msg.state_key }}
                         </span>
                         <span ng-show='msg.content.msgtype === "m.emote"' ng-bind-html="'* ' + (members[msg.user_id].displayname || msg.user_id) + ' ' + msg.content.body | linky:'_blank'"/>
-                        <span ng-show='msg.content.msgtype === "m.text"' ng-bind-html="((msg.content.msgtype === 'm.text') ? msg.content.body : '') | linky:'_blank'"/>
+                        <span ng-show='msg.content.msgtype === "m.text"' 
+                              ng-class="msg.echo_msg_state"
+                              ng-bind-html="((msg.content.msgtype === 'm.text') ? msg.content.body : '') | linky:'_blank'"/>
                         <div ng-show='msg.content.msgtype === "m.image"'>
                             <div ng-hide='msg.content.thumbnail_url' ng-style="msg.content.body.h && { 'height' : (msg.content.body.h < 320) ? msg.content.body.h : 320}">
                                 <img class="image" ng-src="{{ msg.content.url }}"/>