diff --git a/lib/sync.js b/lib/sync.js index f890fea50..36bd260ea 100644 --- a/lib/sync.js +++ b/lib/sync.js @@ -426,7 +426,122 @@ SyncApi.prototype._sync = function(syncOptions, attempt) { // - The isBrandNewRoom boilerplate is boilerplatey. try { - self._processSyncResponse(data); + // handle presence events (User objects) + if (data.presence && utils.isArray(data.presence.events)) { + data.presence.events.map(client.getEventMapper()).forEach( + function(presenceEvent) { + var user = client.store.getUser(presenceEvent.getSender()); + if (user) { + user.setPresenceEvent(presenceEvent); + } + else { + user = createNewUser(client, presenceEvent.getSender()); + user.setPresenceEvent(presenceEvent); + client.store.storeUser(user); + } + client.emit("event", presenceEvent); + }); + } + + // the returned json structure is abit crap, so make it into a + // nicer form (array) after applying sanity to make sure we don't fail + // on missing keys (on the off chance) + var inviteRooms = []; + var joinRooms = []; + var leaveRooms = []; + + if (data.rooms) { + if (data.rooms.invite) { + inviteRooms = self._mapSyncResponseToRoomArray(data.rooms.invite); + } + if (data.rooms.join) { + joinRooms = self._mapSyncResponseToRoomArray(data.rooms.join); + } + if (data.rooms.leave) { + leaveRooms = self._mapSyncResponseToRoomArray(data.rooms.leave); + } + } + + // Handle invites + inviteRooms.forEach(function(inviteObj) { + var room = inviteObj.room; + var stateEvents = + self._mapSyncEventsFormat(inviteObj.invite_state, room); + self._processRoomEvents(room, stateEvents); + if (inviteObj.isBrandNewRoom) { + room.recalculate(client.credentials.userId); + client.store.storeRoom(room); + client.emit("Room", room); + } + stateEvents.forEach(function(e) { client.emit("event", e); }); + }); + + // Handle joins + joinRooms.forEach(function(joinObj) { + var room = joinObj.room; + var stateEvents = self._mapSyncEventsFormat(joinObj.state, room); + var timelineEvents = self._mapSyncEventsFormat(joinObj.timeline, room); + var ephemeralEvents = self._mapSyncEventsFormat(joinObj.ephemeral); + var accountDataEvents = self._mapSyncEventsFormat(joinObj.account_data); + + // we do this first so it's correct when any of the events fire + if (joinObj.unread_notifications) { + room.setUnreadNotificationCount( + 'total', joinObj.unread_notifications.notification_count + ); + room.setUnreadNotificationCount( + 'highlight', joinObj.unread_notifications.highlight_count + ); + } + + joinObj.timeline = joinObj.timeline || {}; + + if (joinObj.timeline.limited) { + // nuke the timeline so we don't get holes + self._deregisterStateListeners(room); + room.resetLiveTimeline(); + self._registerStateListeners(room); + } + + // we want to set a new pagination token if this is the first time + // we've made this room or if we're nuking the timeline + var paginationToken = null; + if (joinObj.isBrandNewRoom || joinObj.timeline.limited) { + paginationToken = joinObj.timeline.prev_batch; + } + + self._processRoomEvents( + room, stateEvents, timelineEvents, paginationToken + ); + + // XXX: should we be adding ephemeralEvents to the timeline? + // It feels like that for symmetry with room.addAccountData() + // there should be a room.addEphemeralEvents() or similar. + room.addEvents(ephemeralEvents); + + // we deliberately don't add accountData to the timeline + room.addAccountData(accountDataEvents); + + room.recalculate(client.credentials.userId); + if (joinObj.isBrandNewRoom) { + client.store.storeRoom(room); + client.emit("Room", room); + } + stateEvents.forEach(function(e) { client.emit("event", e); }); + timelineEvents.forEach(function(e) { client.emit("event", e); }); + ephemeralEvents.forEach(function(e) { client.emit("event", e); }); + accountDataEvents.forEach(function(e) { client.emit("event", e); }); + }); + + // Handle leaves + leaveRooms.forEach(function(leaveObj) { + // Do the bear minimum to register rejected invites / you leaving rooms + var room = leaveObj.room; + var timelineEvents = + self._mapSyncEventsFormat(leaveObj.timeline, room); + room.addEvents(timelineEvents); + timelineEvents.forEach(function(e) { client.emit("event", e); }); + }); } catch (e) { console.error("Caught /sync error:"); @@ -475,128 +590,6 @@ SyncApi.prototype._sync = function(syncOptions, attempt) { }); }; -SyncApi.prototype._processSyncResponse = function(data) { - var client = this.client; - var self = this; - - // handle presence events (User objects) - if (data.presence && utils.isArray(data.presence.events)) { - data.presence.events.map(client.getEventMapper()).forEach( - function(presenceEvent) { - var user = client.store.getUser(presenceEvent.getSender()); - if (user) { - user.setPresenceEvent(presenceEvent); - } - else { - user = createNewUser(client, presenceEvent.getSender()); - user.setPresenceEvent(presenceEvent); - client.store.storeUser(user); - } - client.emit("event", presenceEvent); - }); - } - - // the returned json structure is abit crap, so make it into a - // nicer form (array) after applying sanity to make sure we don't fail - // on missing keys (on the off chance) - var inviteRooms = []; - var joinRooms = []; - var leaveRooms = []; - - if (data.rooms) { - if (data.rooms.invite) { - inviteRooms = this._mapSyncResponseToRoomArray(data.rooms.invite); - } - if (data.rooms.join) { - joinRooms = this._mapSyncResponseToRoomArray(data.rooms.join); - } - if (data.rooms.leave) { - leaveRooms = this._mapSyncResponseToRoomArray(data.rooms.leave); - } - } - - // Handle invites - inviteRooms.forEach(function(inviteObj) { - var room = inviteObj.room; - var stateEvents = - self._mapSyncEventsFormat(inviteObj.invite_state, room); - self._processRoomEvents(room, stateEvents); - if (inviteObj.isBrandNewRoom) { - room.recalculate(client.credentials.userId); - client.store.storeRoom(room); - client.emit("Room", room); - } - stateEvents.forEach(function(e) { client.emit("event", e); }); - }); - - // Handle joins - joinRooms.forEach(function(joinObj) { - var room = joinObj.room; - var stateEvents = self._mapSyncEventsFormat(joinObj.state, room); - var timelineEvents = self._mapSyncEventsFormat(joinObj.timeline, room); - var ephemeralEvents = self._mapSyncEventsFormat(joinObj.ephemeral); - var accountDataEvents = self._mapSyncEventsFormat(joinObj.account_data); - - // we do this first so it's correct when any of the events fire - if (joinObj.unread_notifications) { - room.setUnreadNotificationCount( - 'total', joinObj.unread_notifications.notification_count - ); - room.setUnreadNotificationCount( - 'highlight', joinObj.unread_notifications.highlight_count - ); - } - - joinObj.timeline = joinObj.timeline || {}; - - if (joinObj.timeline.limited) { - // nuke the timeline so we don't get holes - self._deregisterStateListeners(room); - room.resetLiveTimeline(); - self._registerStateListeners(room); - } - - // we want to set a new pagination token if this is the first time - // we've made this room or if we're nuking the timeline - var paginationToken = null; - if (joinObj.isBrandNewRoom || joinObj.timeline.limited) { - paginationToken = joinObj.timeline.prev_batch; - } - - self._processRoomEvents( - room, stateEvents, timelineEvents, paginationToken - ); - - // XXX: should we be adding ephemeralEvents to the timeline? - // It feels like that for symmetry with room.addAccountData() - // there should be a room.addEphemeralEvents() or similar. - room.addEvents(ephemeralEvents); - - // we deliberately don't add accountData to the timeline - room.addAccountData(accountDataEvents); - - room.recalculate(client.credentials.userId); - if (joinObj.isBrandNewRoom) { - client.store.storeRoom(room); - client.emit("Room", room); - } - stateEvents.forEach(function(e) { client.emit("event", e); }); - timelineEvents.forEach(function(e) { client.emit("event", e); }); - ephemeralEvents.forEach(function(e) { client.emit("event", e); }); - accountDataEvents.forEach(function(e) { client.emit("event", e); }); - }); - - // Handle leaves - leaveRooms.forEach(function(leaveObj) { - // Do the bear minimum to register rejected invites / you leaving rooms - var room = leaveObj.room; - var timelineEvents = - self._mapSyncEventsFormat(leaveObj.timeline, room); - room.addEvents(timelineEvents); - timelineEvents.forEach(function(e) { client.emit("event", e); }); - }); -}; - /** * @return {Promise} */