diff --git a/webclient/app-controller.js b/webclient/app-controller.js index 086fa3d94..7f5f93ef7 100644 --- a/webclient/app-controller.js +++ b/webclient/app-controller.js @@ -21,8 +21,8 @@ limitations under the License. 'use strict'; angular.module('MatrixWebClientController', ['matrixService']) -.controller('MatrixWebClientController', ['$scope', '$location', '$rootScope', 'matrixService', - function($scope, $location, $rootScope, matrixService) { +.controller('MatrixWebClientController', ['$scope', '$location', '$rootScope', 'matrixService', 'eventStreamService', + function($scope, $location, $rootScope, matrixService, eventStreamService) { // Check current URL to avoid to display the logout button on the login page $scope.location = $location.path(); @@ -44,11 +44,15 @@ angular.module('MatrixWebClientController', ['matrixService']) else { $scope.config = matrixService.config(); } - }; - + }; + + eventStreamService.resume(); // Logs the user out $scope.logout = function() { + // kill the event stream + eventStreamService.stop(); + // Clean permanent data matrixService.setConfig({}); matrixService.saveConfig(); @@ -57,7 +61,7 @@ angular.module('MatrixWebClientController', ['matrixService']) $location.path("login"); }; - // Listen to the event indicating that the access token is no more valid. + // Listen to the event indicating that the access token is no longer valid. // In this case, the user needs to log in again. $scope.$on("M_UNKNOWN_TOKEN", function() { console.log("Invalid access token -> log user out"); @@ -65,4 +69,4 @@ angular.module('MatrixWebClientController', ['matrixService']) }); }]); - \ No newline at end of file + diff --git a/webclient/app.js b/webclient/app.js index bc78eb9d1..6e0351067 100644 --- a/webclient/app.js +++ b/webclient/app.js @@ -61,12 +61,16 @@ matrixWebClient.config(['$routeProvider', '$provide', '$httpProvider', $httpProvider.interceptors.push('AccessTokenInterceptor'); }]); -matrixWebClient.run(['$location', 'matrixService' , function($location, matrixService) { +matrixWebClient.run(['$location', 'matrixService', 'eventStreamService', function($location, matrixService, eventStreamService) { // If we have no persistent login information, go to the login page var config = matrixService.config(); if (!config || !config.access_token) { + eventStreamService.stop(); $location.path("login"); } + else { + eventStreamService.resume(); + } }]); matrixWebClient diff --git a/webclient/components/matrix/event-stream-service.js b/webclient/components/matrix/event-stream-service.js index 1cb9960b9..97018df88 100644 --- a/webclient/components/matrix/event-stream-service.js +++ b/webclient/components/matrix/event-stream-service.js @@ -19,19 +19,21 @@ limitations under the License. /* This service manages where in the event stream the web client currently is and provides methods to resume/pause/stop the event stream. This service is not -responsible for parsing event data. For that, see the eventDataHandler. +responsible for parsing event data. For that, see the eventHandlerService. */ angular.module('eventStreamService', []) -.factory('eventStreamService', ['matrixService', function(matrixService) { +.factory('eventStreamService', ['$q', '$timeout', 'matrixService', 'eventHandlerService', function($q, $timeout, matrixService, eventHandlerService) { var END = "END"; var START = "START"; var TIMEOUT_MS = 5000; + var ERR_TIMEOUT_MS = 5000; var settings = { from: "END", to: undefined, limit: undefined, - shouldPoll: true + shouldPoll: true, + isActive: false }; // interrupts the stream. Only valid if there is a stream conneciton @@ -39,19 +41,69 @@ angular.module('eventStreamService', []) var interrupt = function(shouldPoll) { console.log("p[EventStream] interrupt("+shouldPoll+") "+ JSON.stringify(settings)); + settings.shouldPoll = shouldPoll; + settings.isActive = false; }; var saveStreamSettings = function() { localStorage.setItem("streamSettings", JSON.stringify(settings)); }; + var startEventStream = function() { + settings.shouldPoll = true; + settings.isActive = true; + var deferred = $q.defer(); + // run the stream from the latest token + matrixService.getEventStream(settings.from, TIMEOUT_MS).then( + function(response) { + if (!settings.isActive) { + console.log("[EventStream] Got response but now inactive. Dropping data."); + return; + } + + settings.from = response.data.end; + + console.log("[EventStream] Got response from "+settings.from+" to "+response.data.end); + eventHandlerService.handleEvents(response.data.chunk, true); + + deferred.resolve(response); + + if (settings.shouldPoll) { + $timeout(startEventStream, 0); + } + else { + console.log("[EventStream] Stopping poll."); + } + }, + function(error) { + if (error.status == 403) { + settings.shouldPoll = false; + } + + deferred.reject(error); + + if (settings.shouldPoll) { + $timeout(startEventStream, ERR_TIMEOUT_MS); + } + else { + console.log("[EventStream] Stopping polling."); + } + } + ); + return deferred.promise; + }; + return { // resume the stream from whereever it last got up to. Typically used // when the page is opened. resume: function() { + if (settings.isActive) { + console.log("[EventStream] Already active, ignoring resume()"); + return; + } + console.log("[EventStream] resume "+JSON.stringify(settings)); - // run the stream from the latest token - return matrixService.getEventStream(settings.from, TIMEOUT_MS); + return startEventStream(); }, // pause the stream. Resuming it will continue from the current position diff --git a/webclient/login/login-controller.js b/webclient/login/login-controller.js index 8bd6a4e84..aa928ef48 100644 --- a/webclient/login/login-controller.js +++ b/webclient/login/login-controller.js @@ -1,6 +1,6 @@ angular.module('LoginController', ['matrixService']) -.controller('LoginController', ['$scope', '$location', 'matrixService', - function($scope, $location, matrixService) { +.controller('LoginController', ['$scope', '$location', 'matrixService', 'eventStreamService', + function($scope, $location, matrixService, eventStreamService) { 'use strict'; @@ -51,7 +51,7 @@ angular.module('LoginController', ['matrixService']) // And permanently save it matrixService.saveConfig(); - + eventStreamService.resume(); // Go to the user's rooms list page $location.path("rooms"); }, @@ -83,6 +83,7 @@ angular.module('LoginController', ['matrixService']) access_token: response.data.access_token }); matrixService.saveConfig(); + eventStreamService.resume(); $location.path("rooms"); } else { diff --git a/webclient/room/room-controller.js b/webclient/room/room-controller.js index 4c5415eac..49c73ff4b 100644 --- a/webclient/room/room-controller.js +++ b/webclient/room/room-controller.js @@ -119,7 +119,6 @@ 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.data.displayname); member.displayname = response.data.displayname; } } @@ -128,7 +127,6 @@ 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.data.avatar_url); member.avatar_url = response.data.avatar_url; } } @@ -204,8 +202,6 @@ angular.module('RoomController', []) matrixService.join($scope.room_id).then( function() { 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(