From 96cd467cfa129acaf8814e574c7cc2a9a94459c5 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Wed, 12 Nov 2014 14:55:57 +0000 Subject: Add recents-service to store shared state between recents-controllers. Remove the selectedRoomId from rootScope and instead store it in recents-service. Add a broadcast to notify listeners (recents-controller) to updates of this. --- .../webclient/components/matrix/recents-service.js | 51 ++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 syweb/webclient/components/matrix/recents-service.js (limited to 'syweb/webclient/components') diff --git a/syweb/webclient/components/matrix/recents-service.js b/syweb/webclient/components/matrix/recents-service.js new file mode 100644 index 0000000000..64d1ab93b4 --- /dev/null +++ b/syweb/webclient/components/matrix/recents-service.js @@ -0,0 +1,51 @@ +/* +Copyright 2014 OpenMarket Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +'use strict'; + +/* +This service manages shared state between *instances* of recent lists. The +recents controller will hook into this central service to get things like: +- which rooms should be highlighted +- which rooms have been binged +- which room is currently selected +- etc. +This is preferable to polluting the $rootScope with recents specific info, and +makes the dependency on this shared state *explicit*. +*/ +angular.module('recentsService', []) +.factory('recentsService', ['$rootScope', function($rootScope) { + // notify listeners when variables in the service are updated. We need to do + // this since we do not tie them to any scope. + var BROADCAST_SELECTED_ROOM_ID = "recentsService:BROADCAST_SELECTED_ROOM_ID"; + var selectedRoomId = undefined; + + + return { + BROADCAST_SELECTED_ROOM_ID: BROADCAST_SELECTED_ROOM_ID, + + getSelectedRoomId: function() { + return selectedRoomId; + }, + + setSelectedRoomId: function(room_id) { + selectedRoomId = room_id; + $rootScope.$broadcast(BROADCAST_SELECTED_ROOM_ID, room_id); + } + + }; + +}]); -- cgit 1.5.1 From 99c445a6d69f0560c08c0264d9b844a4b03599b6 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Wed, 12 Nov 2014 15:11:34 +0000 Subject: Migrate unread messages logic to recentsService. --- .../webclient/components/matrix/recents-service.js | 31 ++++++++++++++++++++-- syweb/webclient/recents/recents-controller.js | 26 +++++------------- 2 files changed, 36 insertions(+), 21 deletions(-) (limited to 'syweb/webclient/components') diff --git a/syweb/webclient/components/matrix/recents-service.js b/syweb/webclient/components/matrix/recents-service.js index 64d1ab93b4..237f1e3912 100644 --- a/syweb/webclient/components/matrix/recents-service.js +++ b/syweb/webclient/components/matrix/recents-service.js @@ -27,15 +27,31 @@ This is preferable to polluting the $rootScope with recents specific info, and makes the dependency on this shared state *explicit*. */ angular.module('recentsService', []) -.factory('recentsService', ['$rootScope', function($rootScope) { +.factory('recentsService', ['$rootScope', 'eventHandlerService', function($rootScope, eventHandlerService) { // notify listeners when variables in the service are updated. We need to do // this since we do not tie them to any scope. - var BROADCAST_SELECTED_ROOM_ID = "recentsService:BROADCAST_SELECTED_ROOM_ID"; + var BROADCAST_SELECTED_ROOM_ID = "recentsService:BROADCAST_SELECTED_ROOM_ID(room_id)"; var selectedRoomId = undefined; + var BROADCAST_UNREAD_MESSAGES = "recentsService:BROADCAST_UNREAD_MESSAGES(room_id, unreadCount)"; + var unreadMessages = { + // room_id: + }; + + // listen for new unread messages + $rootScope.$on(eventHandlerService.MSG_EVENT, function(ngEvent, event, isLive) { + if (isLive && event.room_id !== selectedRoomId) { + if (!unreadMessages[event.room_id]) { + unreadMessages[event.room_id] = 0; + } + unreadMessages[event.room_id] += 1; + $rootScope.$broadcast(BROADCAST_UNREAD_MESSAGES, event.room_id, unreadMessages[event.room_id]); + } + }); return { BROADCAST_SELECTED_ROOM_ID: BROADCAST_SELECTED_ROOM_ID, + BROADCAST_UNREAD_MESSAGES: BROADCAST_UNREAD_MESSAGES, getSelectedRoomId: function() { return selectedRoomId; @@ -44,6 +60,17 @@ angular.module('recentsService', []) setSelectedRoomId: function(room_id) { selectedRoomId = room_id; $rootScope.$broadcast(BROADCAST_SELECTED_ROOM_ID, room_id); + }, + + getUnreadMessages: function() { + return unreadMessages; + }, + + markAsRead: function(room_id) { + if (unreadMessages[room_id]) { + unreadMessages[room_id] = 0; + } + $rootScope.$broadcast(BROADCAST_UNREAD_MESSAGES, room_id, 0); } }; diff --git a/syweb/webclient/recents/recents-controller.js b/syweb/webclient/recents/recents-controller.js index 78aeca128d..5c2cf270c3 100644 --- a/syweb/webclient/recents/recents-controller.js +++ b/syweb/webclient/recents/recents-controller.js @@ -26,34 +26,22 @@ angular.module('RecentsController', ['matrixService', 'matrixFilter']) // retrieve all rooms and expose them $scope.rooms = modelService.getRooms(); - if (!$rootScope.unreadMessages) { - $rootScope.unreadMessages = { - // room_id: - }; - } - + // track the selected room ID: the html will use this $scope.recentsSelectedRoomID = recentsService.getSelectedRoomId(); $scope.$on(recentsService.BROADCAST_SELECTED_ROOM_ID, function(ngEvent, room_id) { $scope.recentsSelectedRoomID = room_id; }); + // track the list of unread messages: the html will use this + $scope.unreadMessages = recentsService.getUnreadMessages(); + $scope.$on(recentsService.BROADCAST_UNREAD_MESSAGES, function(ngEvent, room_id, unreadCount) { + $scope.unreadMessages = recentsService.getUnreadMessages(); + }); $scope.selectRoom = function(room) { - if ($rootScope.unreadMessages[room.room_id]) { - $rootScope.unreadMessages[room.room_id] = 0; - } + recentsService.markAsRead(room.room_id); $rootScope.goToPage('room/' + (room.room_alias ? room.room_alias : room.room_id) ); }; - - $scope.$on(eventHandlerService.MSG_EVENT, function(ngEvent, event, isLive) { - if (isLive && event.room_id !== $scope.recentsSelectedRoomID) { - if (!$rootScope.unreadMessages[event.room_id]) { - $rootScope.unreadMessages[event.room_id] = 0; - } - $rootScope.unreadMessages[event.room_id] += 1; - console.log("sel="+$scope.recentsSelectedRoomID+" unread:"+JSON.stringify($rootScope.unreadMessages, undefined, 2)); - } - }); }]); -- cgit 1.5.1 From 960b28c90a6ca8b9c61a3b376b4f9223203f4f06 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Wed, 12 Nov 2014 15:31:06 +0000 Subject: SYWEB-57: Highlight rooms which have had their bingers go off in blue. Priority is the same as xchat so selected > blue > red. --- syweb/webclient/app.css | 4 ++++ .../components/matrix/event-handler-service.js | 24 ++++++++++++++++------ .../webclient/components/matrix/recents-service.js | 21 +++++++++++++++++++ syweb/webclient/recents/recents-controller.js | 6 ++++++ syweb/webclient/recents/recents.html | 2 +- 5 files changed, 50 insertions(+), 7 deletions(-) (limited to 'syweb/webclient/components') diff --git a/syweb/webclient/app.css b/syweb/webclient/app.css index 7a4ff0467b..648388cdb9 100755 --- a/syweb/webclient/app.css +++ b/syweb/webclient/app.css @@ -816,6 +816,10 @@ textarea, input { background-color: #fee; } +.recentsRoomBing { + background-color: #eef; +} + .recentsRoomName { font-size: 16px; padding-top: 7px; diff --git a/syweb/webclient/components/matrix/event-handler-service.js b/syweb/webclient/components/matrix/event-handler-service.js index 7b2a75507d..6645d20374 100644 --- a/syweb/webclient/components/matrix/event-handler-service.js +++ b/syweb/webclient/components/matrix/event-handler-service.js @@ -95,14 +95,22 @@ function(matrixService, $rootScope, $q, $timeout, $filter, mPresence, notificati modelService.createRoomIdToAliasMapping(event.room_id, event.content.aliases[0]); }; + var containsBingWord = function(event) { + if (!event.content || !event.content.body) { + return false; + } + + return notificationService.containsBingWord( + matrixService.config().user_id, + matrixService.config().display_name, + matrixService.config().bingWords, + event.content.body + ); + }; + var displayNotification = function(event) { if (window.Notification && event.user_id != matrixService.config().user_id) { - var shouldBing = notificationService.containsBingWord( - matrixService.config().user_id, - matrixService.config().display_name, - matrixService.config().bingWords, - event.content.body - ); + var shouldBing = containsBingWord(event); // Ideally we would notify only when the window is hidden (i.e. document.hidden = true). // @@ -529,6 +537,10 @@ function(matrixService, $rootScope, $q, $timeout, $filter, mPresence, notificati resetRoomMessages(room_id); }, + eventContainsBingWord: function(event) { + return containsBingWord(event); + }, + /** * Return the last message event of a room * @param {String} room_id the room id diff --git a/syweb/webclient/components/matrix/recents-service.js b/syweb/webclient/components/matrix/recents-service.js index 237f1e3912..3d82b8218b 100644 --- a/syweb/webclient/components/matrix/recents-service.js +++ b/syweb/webclient/components/matrix/recents-service.js @@ -38,9 +38,22 @@ angular.module('recentsService', []) // room_id: }; + var BROADCAST_UNREAD_BING_MESSAGES = "recentsService:BROADCAST_UNREAD_BING_MESSAGES(room_id, event)"; + var unreadBingMessages = { + // room_id: bingEvent + }; + // listen for new unread messages $rootScope.$on(eventHandlerService.MSG_EVENT, function(ngEvent, event, isLive) { if (isLive && event.room_id !== selectedRoomId) { + if (eventHandlerService.eventContainsBingWord(event)) { + if (!unreadBingMessages[event.room_id]) { + unreadBingMessages[event.room_id] = {}; + } + unreadBingMessages[event.room_id] = event; + $rootScope.$broadcast(BROADCAST_UNREAD_BING_MESSAGES, event.room_id, event); + } + if (!unreadMessages[event.room_id]) { unreadMessages[event.room_id] = 0; } @@ -66,11 +79,19 @@ angular.module('recentsService', []) return unreadMessages; }, + getUnreadBingMessages: function() { + return unreadBingMessages; + }, + markAsRead: function(room_id) { if (unreadMessages[room_id]) { unreadMessages[room_id] = 0; } + if (unreadBingMessages[room_id]) { + unreadBingMessages[room_id] = undefined; + } $rootScope.$broadcast(BROADCAST_UNREAD_MESSAGES, room_id, 0); + $rootScope.$broadcast(BROADCAST_UNREAD_BING_MESSAGES, room_id, undefined); } }; diff --git a/syweb/webclient/recents/recents-controller.js b/syweb/webclient/recents/recents-controller.js index 5c2cf270c3..41720d4cb0 100644 --- a/syweb/webclient/recents/recents-controller.js +++ b/syweb/webclient/recents/recents-controller.js @@ -38,6 +38,12 @@ angular.module('RecentsController', ['matrixService', 'matrixFilter']) $scope.unreadMessages = recentsService.getUnreadMessages(); }); + // track the list of unread BING messages: the html will use this + $scope.unreadBings = recentsService.getUnreadBingMessages(); + $scope.$on(recentsService.BROADCAST_UNREAD_BING_MESSAGES, function(ngEvent, room_id, event) { + $scope.unreadBings = recentsService.getUnreadBingMessages(); + }); + $scope.selectRoom = function(room) { recentsService.markAsRead(room.room_id); $rootScope.goToPage('room/' + (room.room_alias ? room.room_alias : room.room_id) ); diff --git a/syweb/webclient/recents/recents.html b/syweb/webclient/recents/recents.html index 386edb1417..0b3a77ca11 100644 --- a/syweb/webclient/recents/recents.html +++ b/syweb/webclient/recents/recents.html @@ -3,7 +3,7 @@ + ng-class="{'recentsRoomSelected': (room.room_id === recentsSelectedRoomID), 'recentsRoomBing': (unreadBings[room.room_id]), 'recentsRoomUnread': (unreadMessages[room.room_id])}"> {{ room.room_id | mRoomName }} -- cgit 1.5.1 From 9412110c825915f5323d7d266c488c006d26afe3 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 12 Nov 2014 15:35:46 +0000 Subject: comment typo --- syweb/webclient/components/matrix/matrix-call.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'syweb/webclient/components') diff --git a/syweb/webclient/components/matrix/matrix-call.js b/syweb/webclient/components/matrix/matrix-call.js index b560cf7daa..7687cb6971 100644 --- a/syweb/webclient/components/matrix/matrix-call.js +++ b/syweb/webclient/components/matrix/matrix-call.js @@ -82,7 +82,7 @@ angular.module('MatrixCall', []) }); } - // FIXME: we should prevent any class from being placed or accepted before this has finished + // FIXME: we should prevent any calls from being placed or accepted before this has finished MatrixCall.getTurnServer(); MatrixCall.CALL_TIMEOUT = 60000; -- cgit 1.5.1 From 3d3f692fd8a3fe07daf2f5b8811ebc00846b60c1 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Wed, 12 Nov 2014 16:22:14 +0000 Subject: Add test coverage to the webclient. Update .gitignore --- .gitignore | 3 ++- syweb/webclient/components/matrix/matrix-service.js | 2 +- syweb/webclient/test/karma.conf.js | 16 +++++++++++++++- 3 files changed, 18 insertions(+), 3 deletions(-) (limited to 'syweb/webclient/components') diff --git a/.gitignore b/.gitignore index 3d14ac8c03..339a99e0d6 100644 --- a/.gitignore +++ b/.gitignore @@ -34,6 +34,7 @@ graph/*.png graph/*.dot **/webclient/config.js -webclient/test/environment-protractor.js +**/webclient/test/coverage/ +**/webclient/test/environment-protractor.js uploads diff --git a/syweb/webclient/components/matrix/matrix-service.js b/syweb/webclient/components/matrix/matrix-service.js index c1264887c8..cfe8691f85 100644 --- a/syweb/webclient/components/matrix/matrix-service.js +++ b/syweb/webclient/components/matrix/matrix-service.js @@ -23,7 +23,7 @@ This serves to isolate the caller from changes to the underlying url paths, as well as attach common params (e.g. access_token) to requests. */ angular.module('matrixService', []) -.factory('matrixService', ['$http', '$q', '$rootScope', function($http, $q, $rootScope) { +.factory('matrixService', ['$http', '$q', function($http, $q) { /* * Permanent storage of user information diff --git a/syweb/webclient/test/karma.conf.js b/syweb/webclient/test/karma.conf.js index 5f0642ca33..37a9eaf1c1 100644 --- a/syweb/webclient/test/karma.conf.js +++ b/syweb/webclient/test/karma.conf.js @@ -52,18 +52,32 @@ module.exports = function(config) { // preprocess matching files before serving them to the browser // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor preprocessors: { + '../login/**/*.js': 'coverage', + '../room/**/*.js': 'coverage', + '../components/**/*.js': 'coverage', + '../user/**/*.js': 'coverage', + '../home/**/*.js': 'coverage', + '../recents/**/*.js': 'coverage', + '../settings/**/*.js': 'coverage', + '../app.js': 'coverage' }, // test results reporter to use // possible values: 'dots', 'progress' // available reporters: https://npmjs.org/browse/keyword/karma-reporter - reporters: ['progress', 'junit'], + reporters: ['progress', 'junit', 'coverage'], junitReporter: { outputFile: 'test-results.xml', suite: '' }, + coverageReporter: { + type: 'cobertura', + dir: 'coverage/', + file: 'coverage.xml' + }, + // web server port port: 9876, -- cgit 1.5.1 From 9950ce23342a754e9598419fc1b71cb1dc5c4de6 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 12 Nov 2014 17:34:00 +0000 Subject: Detect OpenWebRTC and add workarounds, but comment out the turn server removal for now so we have a live demo of it not working. --- syweb/webclient/components/matrix/matrix-call.js | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'syweb/webclient/components') diff --git a/syweb/webclient/components/matrix/matrix-call.js b/syweb/webclient/components/matrix/matrix-call.js index 7687cb6971..a1c3aaa103 100644 --- a/syweb/webclient/components/matrix/matrix-call.js +++ b/syweb/webclient/components/matrix/matrix-call.js @@ -92,7 +92,8 @@ angular.module('MatrixCall', []) var pc; if (window.mozRTCPeerConnection) { var iceServers = []; - if (MatrixCall.turnServer) { + // https://github.com/EricssonResearch/openwebrtc/issues/85 + if (MatrixCall.turnServer /*&& !this.isOpenWebRTC()*/) { if (MatrixCall.turnServer.uris) { for (var i = 0; i < MatrixCall.turnServer.uris.length; i++) { iceServers.push({ @@ -110,7 +111,8 @@ angular.module('MatrixCall', []) pc = new window.mozRTCPeerConnection({"iceServers":iceServers}); } else { var iceServers = []; - if (MatrixCall.turnServer) { + // https://github.com/EricssonResearch/openwebrtc/issues/85 + if (MatrixCall.turnServer /*&& !this.isOpenWebRTC()*/) { if (MatrixCall.turnServer.uris) { iceServers.push({ 'urls': MatrixCall.turnServer.uris, @@ -492,6 +494,8 @@ angular.module('MatrixCall', []) $timeout(function() { var vel = self.getRemoteVideoElement(); if (vel.play) vel.play(); + // OpenWebRTC does not support oniceconnectionstatechange yet + if (self.isOpenWebRTC()) self.state = 'connected'; }); } }; @@ -641,5 +645,15 @@ angular.module('MatrixCall', []) return null; }; + MatrixCall.prototype.isOpenWebRTC = function() { + var scripts = angular.element('script'); + for (var i = 0; i < scripts.length; i++) { + if (scripts[i].src.indexOf("owr.js") > -1) { + return true; + } + } + return false; + }; + return MatrixCall; }]); -- cgit 1.5.1