forked from MirrorHub/synapse
Event streaming now happens on an app level, rather than a per-room level. Make eventStreamService manage it's own repolling provided no one calls stop() on it. Couple the stream with eventHandlerService so any controller can just blithely call eventStreamService.resume() and expect to 'get stuff' without having to handle promises (though resume() still returns a promise for that request and proxies it through $q). Kill and reset the stream if you logout.
This commit is contained in:
parent
c51cf4efca
commit
7ddb7a5cbb
5 changed files with 76 additions and 19 deletions
|
@ -21,8 +21,8 @@ limitations under the License.
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('MatrixWebClientController', ['matrixService'])
|
angular.module('MatrixWebClientController', ['matrixService'])
|
||||||
.controller('MatrixWebClientController', ['$scope', '$location', '$rootScope', 'matrixService',
|
.controller('MatrixWebClientController', ['$scope', '$location', '$rootScope', 'matrixService', 'eventStreamService',
|
||||||
function($scope, $location, $rootScope, matrixService) {
|
function($scope, $location, $rootScope, matrixService, eventStreamService) {
|
||||||
|
|
||||||
// Check current URL to avoid to display the logout button on the login page
|
// Check current URL to avoid to display the logout button on the login page
|
||||||
$scope.location = $location.path();
|
$scope.location = $location.path();
|
||||||
|
@ -46,9 +46,13 @@ angular.module('MatrixWebClientController', ['matrixService'])
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
eventStreamService.resume();
|
||||||
|
|
||||||
// Logs the user out
|
// Logs the user out
|
||||||
$scope.logout = function() {
|
$scope.logout = function() {
|
||||||
|
// kill the event stream
|
||||||
|
eventStreamService.stop();
|
||||||
|
|
||||||
// Clean permanent data
|
// Clean permanent data
|
||||||
matrixService.setConfig({});
|
matrixService.setConfig({});
|
||||||
matrixService.saveConfig();
|
matrixService.saveConfig();
|
||||||
|
@ -57,7 +61,7 @@ angular.module('MatrixWebClientController', ['matrixService'])
|
||||||
$location.path("login");
|
$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.
|
// In this case, the user needs to log in again.
|
||||||
$scope.$on("M_UNKNOWN_TOKEN", function() {
|
$scope.$on("M_UNKNOWN_TOKEN", function() {
|
||||||
console.log("Invalid access token -> log user out");
|
console.log("Invalid access token -> log user out");
|
||||||
|
|
|
@ -61,12 +61,16 @@ matrixWebClient.config(['$routeProvider', '$provide', '$httpProvider',
|
||||||
$httpProvider.interceptors.push('AccessTokenInterceptor');
|
$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
|
// If we have no persistent login information, go to the login page
|
||||||
var config = matrixService.config();
|
var config = matrixService.config();
|
||||||
if (!config || !config.access_token) {
|
if (!config || !config.access_token) {
|
||||||
|
eventStreamService.stop();
|
||||||
$location.path("login");
|
$location.path("login");
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
eventStreamService.resume();
|
||||||
|
}
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
matrixWebClient
|
matrixWebClient
|
||||||
|
|
|
@ -19,19 +19,21 @@ limitations under the License.
|
||||||
/*
|
/*
|
||||||
This service manages where in the event stream the web client currently is and
|
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
|
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', [])
|
angular.module('eventStreamService', [])
|
||||||
.factory('eventStreamService', ['matrixService', function(matrixService) {
|
.factory('eventStreamService', ['$q', '$timeout', 'matrixService', 'eventHandlerService', function($q, $timeout, matrixService, eventHandlerService) {
|
||||||
var END = "END";
|
var END = "END";
|
||||||
var START = "START";
|
var START = "START";
|
||||||
var TIMEOUT_MS = 5000;
|
var TIMEOUT_MS = 5000;
|
||||||
|
var ERR_TIMEOUT_MS = 5000;
|
||||||
|
|
||||||
var settings = {
|
var settings = {
|
||||||
from: "END",
|
from: "END",
|
||||||
to: undefined,
|
to: undefined,
|
||||||
limit: undefined,
|
limit: undefined,
|
||||||
shouldPoll: true
|
shouldPoll: true,
|
||||||
|
isActive: false
|
||||||
};
|
};
|
||||||
|
|
||||||
// interrupts the stream. Only valid if there is a stream conneciton
|
// interrupts the stream. Only valid if there is a stream conneciton
|
||||||
|
@ -39,19 +41,69 @@ angular.module('eventStreamService', [])
|
||||||
var interrupt = function(shouldPoll) {
|
var interrupt = function(shouldPoll) {
|
||||||
console.log("p[EventStream] interrupt("+shouldPoll+") "+
|
console.log("p[EventStream] interrupt("+shouldPoll+") "+
|
||||||
JSON.stringify(settings));
|
JSON.stringify(settings));
|
||||||
|
settings.shouldPoll = shouldPoll;
|
||||||
|
settings.isActive = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
var saveStreamSettings = function() {
|
var saveStreamSettings = function() {
|
||||||
localStorage.setItem("streamSettings", JSON.stringify(settings));
|
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 {
|
return {
|
||||||
// resume the stream from whereever it last got up to. Typically used
|
// resume the stream from whereever it last got up to. Typically used
|
||||||
// when the page is opened.
|
// when the page is opened.
|
||||||
resume: function() {
|
resume: function() {
|
||||||
|
if (settings.isActive) {
|
||||||
|
console.log("[EventStream] Already active, ignoring resume()");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
console.log("[EventStream] resume "+JSON.stringify(settings));
|
console.log("[EventStream] resume "+JSON.stringify(settings));
|
||||||
// run the stream from the latest token
|
return startEventStream();
|
||||||
return matrixService.getEventStream(settings.from, TIMEOUT_MS);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// pause the stream. Resuming it will continue from the current position
|
// pause the stream. Resuming it will continue from the current position
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
angular.module('LoginController', ['matrixService'])
|
angular.module('LoginController', ['matrixService'])
|
||||||
.controller('LoginController', ['$scope', '$location', 'matrixService',
|
.controller('LoginController', ['$scope', '$location', 'matrixService', 'eventStreamService',
|
||||||
function($scope, $location, matrixService) {
|
function($scope, $location, matrixService, eventStreamService) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ angular.module('LoginController', ['matrixService'])
|
||||||
|
|
||||||
// And permanently save it
|
// And permanently save it
|
||||||
matrixService.saveConfig();
|
matrixService.saveConfig();
|
||||||
|
eventStreamService.resume();
|
||||||
// Go to the user's rooms list page
|
// Go to the user's rooms list page
|
||||||
$location.path("rooms");
|
$location.path("rooms");
|
||||||
},
|
},
|
||||||
|
@ -83,6 +83,7 @@ angular.module('LoginController', ['matrixService'])
|
||||||
access_token: response.data.access_token
|
access_token: response.data.access_token
|
||||||
});
|
});
|
||||||
matrixService.saveConfig();
|
matrixService.saveConfig();
|
||||||
|
eventStreamService.resume();
|
||||||
$location.path("rooms");
|
$location.path("rooms");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -119,7 +119,6 @@ angular.module('RoomController', [])
|
||||||
function(response) {
|
function(response) {
|
||||||
var member = $scope.members[chunk.target_user_id];
|
var member = $scope.members[chunk.target_user_id];
|
||||||
if (member !== undefined) {
|
if (member !== undefined) {
|
||||||
console.log("Updated displayname "+chunk.target_user_id+" to " + response.data.displayname);
|
|
||||||
member.displayname = response.data.displayname;
|
member.displayname = response.data.displayname;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,7 +127,6 @@ angular.module('RoomController', [])
|
||||||
function(response) {
|
function(response) {
|
||||||
var member = $scope.members[chunk.target_user_id];
|
var member = $scope.members[chunk.target_user_id];
|
||||||
if (member !== undefined) {
|
if (member !== undefined) {
|
||||||
console.log("Updated image for "+chunk.target_user_id+" to " + response.data.avatar_url);
|
|
||||||
member.avatar_url = response.data.avatar_url;
|
member.avatar_url = response.data.avatar_url;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -204,8 +202,6 @@ angular.module('RoomController', [])
|
||||||
matrixService.join($scope.room_id).then(
|
matrixService.join($scope.room_id).then(
|
||||||
function() {
|
function() {
|
||||||
console.log("Joined room "+$scope.room_id);
|
console.log("Joined room "+$scope.room_id);
|
||||||
// Now start reading from the stream
|
|
||||||
$timeout(shortPoll, 0);
|
|
||||||
|
|
||||||
// Get the current member list
|
// Get the current member list
|
||||||
matrixService.getMemberList($scope.room_id).then(
|
matrixService.getMemberList($scope.room_id).then(
|
||||||
|
|
Loading…
Reference in a new issue