Browse Source

gui: Stop log tailing on scroll (#5013)

Audrius Butkevicius 7 years ago
parent
commit
b3007c03bd

+ 2 - 2
gui/default/syncthing/core/logViewerModalView.html

@@ -8,8 +8,8 @@
 
       <div id="log-viewer-log" class="tab-pane in active">
         <label translate ng-if="logging.logEntries.length == 0">Loading...</label>
-        <textarea ng-focus="logging.paused = true" ng-blur="logging.paused = false" id="logViewerText" class="form-control" rows="20" ng-if="logging.logEntries.length != 0" readonly style="font-family: Consolas; font-size: 11px; overflow: auto;">{{ logging.content() }}</textarea>
-        <p translate class="help-block" ng-style="{'visibility': logging.paused ? 'visible' : 'hidden'}">Log tailing paused. Click here to continue.</p>
+        <textarea id="logViewerText" class="form-control" rows="20" ng-if="logging.logEntries.length != 0" readonly style="font-family: Consolas; font-size: 11px; overflow: auto;">{{ logging.content() }}</textarea>
+        <p translate class="help-block" ng-style="{'visibility': logging.paused ? 'visible' : 'hidden'}">Log tailing paused. Scroll to bottom continue.</p>
       </div>
 
       <div id="log-viewer-facilities" class="tab-pane">

+ 21 - 4
gui/default/syncthing/core/syncthingController.js

@@ -1097,8 +1097,14 @@ angular.module('syncthing.core')
             show: function() {
                 $scope.logging.refreshFacilities();
                 $scope.logging.timer = $timeout($scope.logging.fetch);
-                $('#logViewer').modal().on('hidden.bs.modal', function () {
+                var textArea = $('#logViewerText');
+                textArea.on("scroll", $scope.logging.onScroll);
+                $('#logViewer').modal().on('shown.bs.modal', function() {
+                    // Scroll to bottom.
+                    textArea.scrollTop(textArea[0].scrollHeight);
+                }).on('hidden.bs.modal', function () {
                     $timeout.cancel($scope.logging.timer);
+                    textArea.off("scroll", $scope.logging.onScroll);
                     $scope.logging.timer = null;
                     $scope.logging.entries = [];
                 });
@@ -1113,6 +1119,14 @@ angular.module('syncthing.core')
                     .success($scope.logging.refreshFacilities)
                     .error($scope.emitHTTPError);
             },
+            onScroll: function() {
+                var textArea = $('#logViewerText');
+                var scrollTop = textArea.prop('scrollTop');
+                var scrollHeight = textArea.prop('scrollHeight');
+                $scope.logging.paused = scrollHeight > (scrollTop + textArea.outerHeight());
+                // Browser events do not cause redraw, trigger manually.
+                $scope.$apply();
+            },
             timer: null,
             entries: [],
             paused: false,
@@ -1125,7 +1139,7 @@ angular.module('syncthing.core')
             },
             fetch: function() {
                 var textArea = $('#logViewerText');
-                if (textArea.is(":focus")) {
+                if ($scope.logging.paused) {
                     if (!$scope.logging.timer) return;
                     $scope.logging.timer = $timeout($scope.logging.fetch, 500);
                     return;
@@ -1139,11 +1153,14 @@ angular.module('syncthing.core')
                 $http.get(urlbase + '/system/log' + (last ? '?since=' + encodeURIComponent(last) : '')).success(function (data) {
                     if (!$scope.logging.timer) return;
                     $scope.logging.timer = $timeout($scope.logging.fetch, 2000);
-                    if (!textArea.is(":focus")) {
+                    if (!$scope.logging.paused) {
                         if (data.messages) {
                             $scope.logging.entries.push.apply($scope.logging.entries, data.messages);
+                            // Wait for the text area to be redrawn, adding new lines, and then scroll to bottom.
+                            $timeout(function() {
+                                textArea.scrollTop(textArea[0].scrollHeight);
+                            });
                         }
-                        textArea.scrollTop(textArea[0].scrollHeight);
                     }
                 });
             }