summary refs log tree commit diff
path: root/webclient/room
diff options
context:
space:
mode:
Diffstat (limited to 'webclient/room')
-rw-r--r--webclient/room/room-controller.js114
-rw-r--r--webclient/room/room.html6
2 files changed, 82 insertions, 38 deletions
diff --git a/webclient/room/room-controller.js b/webclient/room/room-controller.js
index 470f41521a..fb6e2025fc 100644
--- a/webclient/room/room-controller.js
+++ b/webclient/room/room-controller.js
@@ -18,11 +18,15 @@ angular.module('RoomController', [])
 .controller('RoomController', ['$scope', '$http', '$timeout', '$routeParams', '$location', 'matrixService',
                                function($scope, $http, $timeout, $routeParams, $location, matrixService) {
    'use strict';
+    var MESSAGES_PER_PAGINATION = 10;
     $scope.room_id = $routeParams.room_id;
     $scope.room_alias = matrixService.getRoomIdToAliasMapping($scope.room_id);
     $scope.state = {
         user_id: matrixService.config().user_id,
-        events_from: "START"
+        events_from: "END", // when to start the event stream from.
+        earliest_token: "END", // stores how far back we've paginated.
+        can_paginate: true, // this is toggled off when we run out of items
+        stream_failure: undefined // the response when the stream fails
     };
     $scope.messages = [];
     $scope.members = {};
@@ -30,6 +34,53 @@ angular.module('RoomController', [])
 
     $scope.imageURLToSend = "";
     $scope.userIDToInvite = "";
+    
+    var scrollToBottom = function() {
+        $timeout(function() {
+            var objDiv = document.getElementsByClassName("messageTableWrapper")[0];
+            objDiv.scrollTop = objDiv.scrollHeight;
+        },0);
+    };
+    
+    var parseChunk = function(chunks, appendToStart) {
+        for (var i = 0; i < chunks.length; i++) {
+            var chunk = chunks[i];
+            if (chunk.room_id == $scope.room_id && chunk.type == "m.room.message") {
+                if ("membership_target" in chunk.content) {
+                    chunk.user_id = chunk.content.membership_target;
+                }
+                if (appendToStart) {
+                    $scope.messages.unshift(chunk);
+                }
+                else {
+                    $scope.messages.push(chunk);
+                    scrollToBottom();
+                }
+            }
+            else if (chunk.room_id == $scope.room_id && chunk.type == "m.room.member") {
+                updateMemberList(chunk);
+            }
+            else if (chunk.type === "m.presence") {
+                updatePresence(chunk);
+            }
+        }
+    };
+    
+    var paginate = function(numItems) {
+        matrixService.paginateBackMessages($scope.room_id, $scope.state.earliest_token, numItems).then(
+            function(response) {
+                parseChunk(response.data.chunk, true);
+                $scope.state.earliest_token = response.data.end;
+                if (response.data.chunk.length < MESSAGES_PER_PAGINATION) {
+                    // no more messages to paginate :(
+                    $scope.state.can_paginate = false;
+                }
+            },
+            function(error) {
+                console.log("Failed to paginateBackMessages: " + JSON.stringify(error));
+            }
+        )
+    };
 
     var shortPoll = function() {
         $http.get(matrixService.config().homeserver + matrixService.prefix + "/events", {
@@ -39,30 +90,13 @@ angular.module('RoomController', [])
                 "timeout": 5000
             }})
             .then(function(response) {
+                $scope.state.stream_failure = undefined;
                 console.log("Got response from "+$scope.state.events_from+" to "+response.data.end);
                 $scope.state.events_from = response.data.end;
-
                 $scope.feedback = "";
 
-                for (var i = 0; i < response.data.chunk.length; i++) {
-                    var chunk = response.data.chunk[i];
-                    if (chunk.room_id == $scope.room_id && chunk.type == "m.room.message") {
-                        if ("membership_target" in chunk.content) {
-                            chunk.user_id = chunk.content.membership_target;
-                        }
-                        $scope.messages.push(chunk);
-                        $timeout(function() {
-                            var objDiv = document.getElementsByClassName("messageTableWrapper")[0];
-                            objDiv.scrollTop = objDiv.scrollHeight;
-                        },0);
-                    }
-                    else if (chunk.room_id == $scope.room_id && chunk.type == "m.room.member") {
-                        updateMemberList(chunk);
-                    }
-                    else if (chunk.type === "m.presence") {
-                        updatePresence(chunk);
-                    }
-                }
+                parseChunk(response.data.chunk, false);
+                
                 if ($scope.stopPoll) {
                     console.log("Stopping polling.");
                 }
@@ -70,7 +104,7 @@ angular.module('RoomController', [])
                     $timeout(shortPoll, 0);
                 }
             }, function(response) {
-                $scope.feedback = "Can't stream: " + response.data;
+                $scope.state.stream_failure = response;
 
                 if (response.status == 403) {
                     $scope.stopPoll = true;
@@ -99,8 +133,8 @@ angular.module('RoomController', [])
                     function(response) {
                         var member = $scope.members[chunk.target_user_id];
                         if (member !== undefined) {
-                            console.log("Updated displayname "+chunk.target_user_id+" to " + response.displayname);
-                            member.displayname = response.displayname;
+                            console.log("Updated displayname "+chunk.target_user_id+" to " + response.data.displayname);
+                            member.displayname = response.data.displayname;
                         }
                     }
                 ); 
@@ -108,8 +142,8 @@ angular.module('RoomController', [])
                     function(response) {
                          var member = $scope.members[chunk.target_user_id];
                          if (member !== undefined) {
-                            console.log("Updated image for "+chunk.target_user_id+" to " + response.avatar_url);
-                            member.avatar_url = response.avatar_url;
+                            console.log("Updated image for "+chunk.target_user_id+" to " + response.data.avatar_url);
+                            member.avatar_url = response.data.avatar_url;
                          }
                     }
                 );
@@ -171,8 +205,8 @@ angular.module('RoomController', [])
                 console.log("Sent message");
                 $scope.textInput = "";
             },
-            function(reason) {
-                $scope.feedback = "Failed to send: " + reason;
+            function(error) {
+                $scope.feedback = "Failed to send: " + error.data.error;
             });               
     };
 
@@ -183,22 +217,24 @@ angular.module('RoomController', [])
         // Join the room
         matrixService.join($scope.room_id).then(
             function() {
-                console.log("Joined room");
+                console.log("Joined room "+$scope.room_id);
                 // Now start reading from the stream
                 $timeout(shortPoll, 0);
 
                 // Get the current member list
                 matrixService.getMemberList($scope.room_id).then(
                     function(response) {
-                        for (var i = 0; i < response.chunk.length; i++) {
-                            var chunk = response.chunk[i];
+                        for (var i = 0; i < response.data.chunk.length; i++) {
+                            var chunk = response.data.chunk[i];
                             updateMemberList(chunk);
                         }
                     },
-                    function(reason) {
-                        $scope.feedback = "Failed get member list: " + reason;
+                    function(error) {
+                        $scope.feedback = "Failed get member list: " + error.data.error;
                     }
                 );
+                
+                paginate(MESSAGES_PER_PAGINATION);
             },
             function(reason) {
                 $scope.feedback = "Can't join room: " + reason;
@@ -224,8 +260,8 @@ angular.module('RoomController', [])
                 console.log("Left room ");
                 $location.path("rooms");
             },
-            function(reason) {
-                $scope.feedback = "Failed to leave room: " + reason;
+            function(error) {
+                $scope.feedback = "Failed to leave room: " + error.data.error;
             });
     };
 
@@ -234,10 +270,14 @@ angular.module('RoomController', [])
             function() {
                 console.log("Image sent");
             },
-            function(reason) {
-                $scope.feedback = "Failed to send image: " + reason;
+            function(error) {
+                $scope.feedback = "Failed to send image: " + error.data.error;
             });
     };
+    
+    $scope.loadMoreHistory = function() {
+        paginate(MESSAGES_PER_PAGINATION);
+    };
 
     $scope.$on('$destroy', function(e) {
         console.log("onDestroyed: Stopping poll.");
diff --git a/webclient/room/room.html b/webclient/room/room.html
index 8fc7d5d360..3b9ba713de 100644
--- a/webclient/room/room.html
+++ b/webclient/room/room.html
@@ -35,7 +35,7 @@
                     <div class="bubble">
                         {{ msg.content.msgtype === "m.emote" ? ("* " + (members[msg.user_id].displayname || msg.user_id) + " " + msg.content.body) : "" }}
                         {{ msg.content.msgtype === "m.text" ? msg.content.body : "" }}
-                        <img class="image" ng-hide='msg.content.msgtype !== "m.image"' src="{{ msg.content.url }}" alt="{{ msg.content.body }}"/>
+                        <img class="image" ng-hide='msg.content.msgtype !== "m.image"' ng-src="{{ msg.content.url }}" alt="{{ msg.content.body }}"/>
                     </div>
                 </td>
                 <td class="rightBlock">
@@ -86,6 +86,10 @@
                     <button ng-click="inviteUser(userIDToInvite)">Invite</button>
             </span>
             <button ng-click="leaveRoom()">Leave</button>
+            <button ng-click="loadMoreHistory()" ng-disabled="!state.can_paginate">Load more history</button>
+            <div ng-hide="!state.stream_failure">
+                {{ state.stream_failure.data.error || "Connection failure" }}
+            </div>
         </div>
     </div>