diff options
-rwxr-xr-x | webclient/app.css | 7 | ||||
-rw-r--r-- | webclient/room/room-controller.js | 44 | ||||
-rw-r--r-- | webclient/room/room.html | 9 |
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 }}"/> |