199 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
			
		
		
	
	
			199 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
| /*
 | |
| 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 handles what should happen when you get an event. This service does
 | |
| not care where the event came from, it only needs enough context to be able to 
 | |
| process them. Events may be coming from the event stream, the REST API (via 
 | |
| direct GETs or via a pagination stream API), etc.
 | |
| 
 | |
| Typically, this service will store events or broadcast them to any listeners
 | |
| (e.g. controllers) via $broadcast. Alternatively, it may update the $rootScope
 | |
| if typically all the $on method would do is update its own $scope.
 | |
| */
 | |
| angular.module('eventHandlerService', [])
 | |
| .factory('eventHandlerService', ['matrixService', '$rootScope', '$q', function(matrixService, $rootScope, $q) {
 | |
|     var ROOM_CREATE_EVENT = "ROOM_CREATE_EVENT";
 | |
|     var MSG_EVENT = "MSG_EVENT";
 | |
|     var MEMBER_EVENT = "MEMBER_EVENT";
 | |
|     var PRESENCE_EVENT = "PRESENCE_EVENT";
 | |
|     var POWERLEVEL_EVENT = "POWERLEVEL_EVENT";
 | |
|     var CALL_EVENT = "CALL_EVENT";
 | |
|     var NAME_EVENT = "NAME_EVENT";
 | |
| 
 | |
|     var InitialSyncDeferred = $q.defer();
 | |
|     
 | |
|     $rootScope.events = {
 | |
|         rooms: {} // will contain roomId: { messages:[], members:{userid1: event} }
 | |
|     };
 | |
| 
 | |
|     $rootScope.presence = {};
 | |
|     
 | |
|     var initRoom = function(room_id) {
 | |
|         if (!(room_id in $rootScope.events.rooms)) {
 | |
|             console.log("Creating new handler entry for " + room_id);
 | |
|             $rootScope.events.rooms[room_id] = {};
 | |
|             $rootScope.events.rooms[room_id].messages = [];
 | |
|             $rootScope.events.rooms[room_id].members = {};
 | |
|         }
 | |
|     };
 | |
| 
 | |
|     var resetRoomMessages = function(room_id) {
 | |
|         if ($rootScope.events.rooms[room_id]) {
 | |
|             $rootScope.events.rooms[room_id].messages = [];
 | |
|         }
 | |
|     };
 | |
|     
 | |
|     var handleRoomCreate = function(event, isLiveEvent) {
 | |
|         initRoom(event.room_id);
 | |
| 
 | |
|         // For now, we do not use the event data. Simply signal it to the app controllers
 | |
|         $rootScope.$broadcast(ROOM_CREATE_EVENT, event, isLiveEvent);
 | |
|     };
 | |
| 
 | |
|     var handleMessage = function(event, isLiveEvent) {
 | |
|         initRoom(event.room_id);
 | |
|         
 | |
|         if (isLiveEvent) {
 | |
|             $rootScope.events.rooms[event.room_id].messages.push(event);
 | |
|         }
 | |
|         else {
 | |
|             $rootScope.events.rooms[event.room_id].messages.unshift(event);
 | |
|         }
 | |
|         
 | |
|         // TODO send delivery receipt if isLiveEvent
 | |
|         
 | |
|         // $broadcast this, as controllers may want to do funky things such as
 | |
|         // scroll to the bottom, etc which cannot be expressed via simple $scope
 | |
|         // updates.
 | |
|         $rootScope.$broadcast(MSG_EVENT, event, isLiveEvent);
 | |
|     };
 | |
|     
 | |
|     var handleRoomMember = function(event, isLiveEvent) {
 | |
|         initRoom(event.room_id);
 | |
|         
 | |
|         // add membership changes as if they were a room message if something interesting changed
 | |
|         if (event.content.prev !== event.content.membership) {
 | |
|             if (isLiveEvent) {
 | |
|                 $rootScope.events.rooms[event.room_id].messages.push(event);
 | |
|             }
 | |
|             else {
 | |
|                 $rootScope.events.rooms[event.room_id].messages.unshift(event);
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         $rootScope.events.rooms[event.room_id].members[event.state_key] = event;
 | |
|         $rootScope.$broadcast(MEMBER_EVENT, event, isLiveEvent);
 | |
|     };
 | |
|     
 | |
|     var handlePresence = function(event, isLiveEvent) {
 | |
|         $rootScope.presence[event.content.user_id] = event;
 | |
|         $rootScope.$broadcast(PRESENCE_EVENT, event, isLiveEvent);
 | |
|     };
 | |
|     
 | |
|     var handlePowerLevels = function(event, isLiveEvent) {
 | |
|         initRoom(event.room_id);
 | |
| 
 | |
|         // Keep the latest data. Do not care of events that come when paginating back
 | |
|         if (!$rootScope.events.rooms[event.room_id][event.type] || isLiveEvent) {
 | |
|             $rootScope.events.rooms[event.room_id][event.type] = event;
 | |
|             $rootScope.$broadcast(POWERLEVEL_EVENT, event, isLiveEvent);   
 | |
|         }
 | |
|     };
 | |
| 
 | |
|     var handleRoomName = function(event, isLiveEvent) {
 | |
|         console.log("handleRoomName " + isLiveEvent);
 | |
| 
 | |
|         initRoom(event.room_id);
 | |
| 
 | |
|         $rootScope.events.rooms[event.room_id][event.type] = event;
 | |
|         $rootScope.$broadcast(NAME_EVENT, event, isLiveEvent);
 | |
|     };
 | |
| 
 | |
|     var handleCallEvent = function(event, isLiveEvent) {
 | |
|         $rootScope.$broadcast(CALL_EVENT, event, isLiveEvent);
 | |
|     };
 | |
|     
 | |
|     return {
 | |
|         ROOM_CREATE_EVENT: ROOM_CREATE_EVENT,
 | |
|         MSG_EVENT: MSG_EVENT,
 | |
|         MEMBER_EVENT: MEMBER_EVENT,
 | |
|         PRESENCE_EVENT: PRESENCE_EVENT,
 | |
|         POWERLEVEL_EVENT: POWERLEVEL_EVENT,
 | |
|         CALL_EVENT: CALL_EVENT,
 | |
|         NAME_EVENT: NAME_EVENT,
 | |
|         
 | |
|     
 | |
|         handleEvent: function(event, isLiveEvent) {
 | |
|             switch(event.type) {
 | |
|                 case "m.room.create":
 | |
|                     handleRoomCreate(event, isLiveEvent);
 | |
|                     break;
 | |
|                 case "m.room.message":
 | |
|                     handleMessage(event, isLiveEvent);
 | |
|                     break;
 | |
|                 case "m.room.member":
 | |
|                     handleRoomMember(event, isLiveEvent);
 | |
|                     break;
 | |
|                 case "m.presence":
 | |
|                     handlePresence(event, isLiveEvent);
 | |
|                     break;
 | |
|                 case 'm.room.ops_levels':
 | |
|                 case 'm.room.send_event_level':
 | |
|                 case 'm.room.add_state_level':
 | |
|                 case 'm.room.join_rules':
 | |
|                 case 'm.room.power_levels':
 | |
|                     handlePowerLevels(event, isLiveEvent);
 | |
|                     break;
 | |
|                 case 'm.room.name':
 | |
|                     handleRoomName(event, isLiveEvent);
 | |
|                     break;
 | |
|                 default:
 | |
|                     console.log("Unable to handle event type " + event.type);
 | |
|                     console.log(JSON.stringify(event, undefined, 4));
 | |
|                     break;
 | |
|             }
 | |
|             if (event.type.indexOf('m.call.') === 0) {
 | |
|                 handleCallEvent(event, isLiveEvent);
 | |
|             }
 | |
|         },
 | |
|         
 | |
|         // isLiveEvents determines whether notifications should be shown, whether
 | |
|         // messages get appended to the start/end of lists, etc.
 | |
|         handleEvents: function(events, isLiveEvents) {
 | |
|             for (var i=0; i<events.length; i++) {
 | |
|                 this.handleEvent(events[i], isLiveEvents);
 | |
|             }
 | |
|         },
 | |
| 
 | |
|         handleInitialSyncDone: function() {
 | |
|             console.log("# handleInitialSyncDone");
 | |
|             InitialSyncDeferred.resolve($rootScope.events, $rootScope.presence);
 | |
|         },
 | |
| 
 | |
|         // Returns a promise that resolves when the initialSync request has been processed
 | |
|         waitForInitialSyncCompletion: function() {
 | |
|             return InitialSyncDeferred.promise;
 | |
|         },
 | |
| 
 | |
|         resetRoomMessages: function(room_id) {
 | |
|             resetRoomMessages(room_id);
 | |
|         }
 | |
|     };
 | |
| }]);
 |