summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthew Hodgson <matthew@matrix.org>2014-08-16 00:14:47 +0100
committerMatthew Hodgson <matthew@matrix.org>2014-08-16 00:14:47 +0100
commit4068339770752a361eebb738dd2f6fd1de69f793 (patch)
tree0f33d0031181714ff1e2bdfc5ed7f23833f30f5d
parentswitch some elements from being styled by class to styled by id (diff)
downloadsynapse-4068339770752a361eebb738dd2f6fd1de69f793.tar.xz
slightly hacky but more functional infinite scrolling
-rw-r--r--webclient/room/room-controller.js66
1 files changed, 36 insertions, 30 deletions
diff --git a/webclient/room/room-controller.js b/webclient/room/room-controller.js
index 3fc45bc782..a53d375cf8 100644
--- a/webclient/room/room-controller.js
+++ b/webclient/room/room-controller.js
@@ -15,36 +15,11 @@ limitations under the License.
 */
 
 angular.module('RoomController', [])
-// FIXME move directives outta here!
-.directive("keepScroll", function() {
-    return {
-        controller : function($scope) {
-            var element = 0;
-            this.setElement = function(el){
-                element = el;
-            }
-            this.addItem = function(item){
-                element.scrollTop = (element.scrollTop + item.clientHeight);
-            };
-        },
-        link : function(scope, el, attr, ctrl) {
-            ctrl.setElement(el[0]);
-        }
-    };
-})
-// FIXME move directives outta here!
-.directive("scrollItem", function(){
-    return {
-        require : "^keepScroll",
-        link : function(scope, el, att, scrCtrl){
-            scrCtrl.addItem(el[0]);
-        }
-    }
-})
+
 .controller('RoomController', ['$scope', '$http', '$timeout', '$routeParams', '$location', 'matrixService', 'eventStreamService', 'eventHandlerService',
                                function($scope, $http, $timeout, $routeParams, $location, matrixService, eventStreamService, eventHandlerService) {
    'use strict';
-    var MESSAGES_PER_PAGINATION = 10;
+    var MESSAGES_PER_PAGINATION = 30;
     $scope.room_id = $routeParams.room_id;
     $scope.room_alias = matrixService.getRoomIdToAliasMapping($scope.room_id);
     $scope.state = {
@@ -52,6 +27,7 @@ angular.module('RoomController', [])
         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
+        paginating: false, // used to avoid concurrent pagination requests pulling in dup contents
         stream_failure: undefined // the response when the stream fails
     };
     $scope.members = {};
@@ -61,7 +37,7 @@ angular.module('RoomController', [])
     
     var scrollToBottom = function() {
         $timeout(function() {
-            var objDiv = document.getElementsByClassName("messageTableWrapper")[0];
+            var objDiv = document.getElementById("messageTableWrapper");
             objDiv.scrollTop = objDiv.scrollHeight;
         },0);
     };
@@ -82,18 +58,33 @@ angular.module('RoomController', [])
     
     $scope.paginateMore = function() {
         if ($scope.state.can_paginate) {
-            console.log("Paginating more.");
+            // console.log("Paginating more.");
             paginate(MESSAGES_PER_PAGINATION, false);
         }
     };
     
     var paginate = function(numItems, toBottom) {
+        // console.log("paginate " + numItems + ", " + toBottom);
+        if ($scope.state.paginating) {
+            return;
+        }
+        else {
+            $scope.state.paginating = true;
+        }
+        // console.log("paginateBackMessages from " + $scope.state.earliest_token + " for " + numItems);
+        var originalTopRow = $("#messageTable>tbody>tr:first")[0];
         matrixService.paginateBackMessages($scope.room_id, $scope.state.earliest_token, numItems).then(
             function(response) {
+                // hacky bodge to ensure we always scroll to the bottom on the first pagination
+                if (!$scope.events.rooms[$scope.room_id]) {
+                    toBottom = true;
+                }
+                
                 eventHandlerService.handleEvents(response.data.chunk, false);
                 $scope.state.earliest_token = response.data.end;
                 if (response.data.chunk.length < MESSAGES_PER_PAGINATION) {
-                    // no more messages to paginate :(
+                    // no more messages to paginate. this currently never gets turned true again, as we never
+                    // expire paginated contents in the current implementation.
                     $scope.state.can_paginate = false;
                 }
                 
@@ -101,9 +92,24 @@ angular.module('RoomController', [])
                     console.log("Scrolling to bottom");
                     scrollToBottom();
                 }
+                else {
+                    $timeout(function() {
+                        // FIXME: this risks a flicker before the scrollTop is actually updated, but we have to
+                        // dispatch it into a function in order to first update the layout.  The right solution
+                        // might be to implement it as a directive, more like
+                        // http://stackoverflow.com/questions/23736647/how-to-retain-scroll-position-of-ng-repeat-in-angularjs
+                        // however, this specific solution breaks because it measures the rows height before
+                        // the contents are interpolated.
+                        var objDiv = document.getElementById("messageTableWrapper");
+                        objDiv.scrollTop = originalTopRow ? (originalTopRow.offsetTop + objDiv.scrollTop) : 0;
+                    }, 0);
+                }
+                
+                $scope.state.paginating = false;
             },
             function(error) {
                 console.log("Failed to paginateBackMessages: " + JSON.stringify(error));
+                $scope.state.paginating = false;
             }
         )
     };