author | Ed Lee <edilee@mozilla.com> |
Fri, 28 Aug 2015 01:39:59 -0700 | |
changeset 261290 | ba7eec9f555db8ed6387fe1606574dfdc0bf9c8f |
parent 261289 | fecf8cae8265a9283fa94bf2da62612dc0d1b0c5 |
child 261291 | 466847c2206cbfb6dc4c287d16e910cd93a99d87 |
push id | 64705 |
push user | cbook@mozilla.com |
push date | Tue, 08 Sep 2015 14:02:43 +0000 |
treeherder | mozilla-inbound@7fa38a962661 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | Standard8 |
bugs | 1198841 |
milestone | 43.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/browser/components/loop/content/js/roomViews.js +++ b/browser/components/loop/content/js/roomViews.js @@ -588,18 +588,30 @@ loop.roomViews = (function(mozL10n) { publishStream: function(type, enabled) { this.props.dispatcher.dispatch( new sharedActions.SetMute({ type: type, enabled: enabled })); }, + /** + * Determine if the invitation controls should be shown. + * + * @return {Boolean} True if there's no guests. + */ _shouldRenderInvitationOverlay: function() { - return (this.state.roomState !== ROOM_STATES.HAS_PARTICIPANTS); + var hasGuests = typeof this.state.participants === "object" && + this.state.participants.filter(function(participant) { + return !participant.owner; + }).length > 0; + + // Don't show if the room has participants whether from the room state or + // there being non-owner guests in the participants array. + return this.state.roomState !== ROOM_STATES.HAS_PARTICIPANTS && !hasGuests; }, /** * Works out if remote video should be rended or not, depending on the * room state and other flags. * * @return {Boolean} True if remote video should be rended. *
--- a/browser/components/loop/content/js/roomViews.jsx +++ b/browser/components/loop/content/js/roomViews.jsx @@ -588,18 +588,30 @@ loop.roomViews = (function(mozL10n) { publishStream: function(type, enabled) { this.props.dispatcher.dispatch( new sharedActions.SetMute({ type: type, enabled: enabled })); }, + /** + * Determine if the invitation controls should be shown. + * + * @return {Boolean} True if there's no guests. + */ _shouldRenderInvitationOverlay: function() { - return (this.state.roomState !== ROOM_STATES.HAS_PARTICIPANTS); + var hasGuests = typeof this.state.participants === "object" && + this.state.participants.filter(function(participant) { + return !participant.owner; + }).length > 0; + + // Don't show if the room has participants whether from the room state or + // there being non-owner guests in the participants array. + return this.state.roomState !== ROOM_STATES.HAS_PARTICIPANTS && !hasGuests; }, /** * Works out if remote video should be rended or not, depending on the * room state and other flags. * * @return {Boolean} True if remote video should be rended. *
--- a/browser/components/loop/content/shared/js/activeRoomStore.js +++ b/browser/components/loop/content/shared/js/activeRoomStore.js @@ -46,16 +46,17 @@ loop.store.ActiveRoomStore = (function() var ROOM_STATES = loop.store.ROOM_STATES; var ROOM_INFO_FAILURES = loop.shared.utils.ROOM_INFO_FAILURES; var OPTIONAL_ROOMINFO_FIELDS = { urls: "roomContextUrls", description: "roomDescription", + participants: "participants", roomInfoFailure: "roomInfoFailure", roomName: "roomName", roomState: "roomState" }; /** * Active room store. * @@ -291,16 +292,17 @@ loop.store.ActiveRoomStore = (function() this.dispatchAction(new sharedActions.RoomFailure({ error: error, failedJoinRequest: false })); return; } this.dispatchAction(new sharedActions.SetupRoomInfo({ + participants: roomData.participants, roomToken: actionData.roomToken, roomContextUrls: roomData.decryptedContext.urls, roomDescription: roomData.decryptedContext.description, roomName: roomData.decryptedContext.roomName, roomUrl: roomData.roomUrl, socialShareProviders: this._mozLoop.getSocialShareProviders() })); @@ -413,16 +415,17 @@ loop.store.ActiveRoomStore = (function() */ setupRoomInfo: function(actionData) { if (this._onUpdateListener) { console.error("Room info already set up!"); return; } this.setStoreState({ + participants: actionData.participants, roomContextUrls: actionData.roomContextUrls, roomDescription: actionData.roomDescription, roomName: actionData.roomName, roomState: ROOM_STATES.READY, roomToken: actionData.roomToken, roomUrl: actionData.roomUrl, socialShareProviders: actionData.socialShareProviders }); @@ -444,17 +447,17 @@ loop.store.ActiveRoomStore = (function() */ updateRoomInfo: function(actionData) { var newState = { roomUrl: actionData.roomUrl }; // Iterate over the optional fields that _may_ be present on the actionData // object. Object.keys(OPTIONAL_ROOMINFO_FIELDS).forEach(function(field) { - if (actionData[field]) { + if (actionData[field] !== undefined) { newState[OPTIONAL_ROOMINFO_FIELDS[field]] = actionData[field]; } }); this.setStoreState(newState); }, /** * Handles the updateSocialShareInfo action. Updates the room data with new @@ -473,16 +476,17 @@ loop.store.ActiveRoomStore = (function() * * @param {String} eventName The name of the event * @param {Object} roomData The new roomData. */ _handleRoomUpdate: function(eventName, roomData) { this.dispatchAction(new sharedActions.UpdateRoomInfo({ urls: roomData.decryptedContext.urls, description: roomData.decryptedContext.description, + participants: roomData.participants, roomName: roomData.decryptedContext.roomName, roomUrl: roomData.roomUrl })); }, /** * Handles the deletion of a room, notified by the mozLoop rooms API. * @@ -787,17 +791,26 @@ loop.store.ActiveRoomStore = (function() }, /** * Handles a remote peer disconnecting from the session. As we currently only * support 2 participants, we declare the room as SESSION_CONNECTED as soon as * one participantleaves. */ remotePeerDisconnected: function() { + // Update the participants to just the owner. + var participants = this.getStoreState("participants"); + if (participants) { + participants = participants.filter(function(participant) { + return participant.owner; + }); + } + this.setStoreState({ + participants: participants, roomState: ROOM_STATES.SESSION_CONNECTED, remoteSrcVideoObject: null }); }, /** * Handles an SDK status update, forwarding it to the server. *
--- a/browser/components/loop/test/desktop-local/roomViews_test.js +++ b/browser/components/loop/test/desktop-local/roomViews_test.js @@ -465,28 +465,73 @@ describe("loop.roomViews", function () { }); it("should render the DesktopRoomInvitationView if roomState is `JOINED`", function() { activeRoomStore.setStoreState({roomState: ROOM_STATES.JOINED}); view = mountTestComponent(); + expect(TestUtils.findRenderedComponentWithType(view, + loop.roomViews.DesktopRoomInvitationView).getDOMNode()).to.not.eql(null); + }); + + it("should render the DesktopRoomInvitationView if roomState is `JOINED` with just owner", + function() { + activeRoomStore.setStoreState({ + participants: [{owner: true}], + roomState: ROOM_STATES.JOINED + }); + + view = mountTestComponent(); + + expect(TestUtils.findRenderedComponentWithType(view, + loop.roomViews.DesktopRoomInvitationView).getDOMNode()).to.not.eql(null); + }); + + it("should render the DesktopRoomConversationView if roomState is `JOINED` with remote participant", + function() { + activeRoomStore.setStoreState({ + participants: [{}], + roomState: ROOM_STATES.JOINED + }); + + view = mountTestComponent(); + TestUtils.findRenderedComponentWithType(view, - loop.roomViews.DesktopRoomInvitationView); + loop.roomViews.DesktopRoomConversationView); + expect(TestUtils.findRenderedComponentWithType(view, + loop.roomViews.DesktopRoomInvitationView).getDOMNode()).to.eql(null); + }); + + it("should render the DesktopRoomConversationView if roomState is `JOINED` with participants", + function() { + activeRoomStore.setStoreState({ + participants: [{owner: true}, {}], + roomState: ROOM_STATES.JOINED + }); + + view = mountTestComponent(); + + TestUtils.findRenderedComponentWithType(view, + loop.roomViews.DesktopRoomConversationView); + expect(TestUtils.findRenderedComponentWithType(view, + loop.roomViews.DesktopRoomInvitationView).getDOMNode()).to.eql(null); }); it("should render the DesktopRoomConversationView if roomState is `HAS_PARTICIPANTS`", function() { activeRoomStore.setStoreState({roomState: ROOM_STATES.HAS_PARTICIPANTS}); view = mountTestComponent(); TestUtils.findRenderedComponentWithType(view, loop.roomViews.DesktopRoomConversationView); + expect(TestUtils.findRenderedComponentWithType(view, + loop.roomViews.DesktopRoomInvitationView).getDOMNode()).to.eql(null); }); it("should call onCallTerminated when the call ended", function() { activeRoomStore.setStoreState({ roomState: ROOM_STATES.ENDED, used: true });
--- a/browser/components/loop/test/shared/activeRoomStore_test.js +++ b/browser/components/loop/test/shared/activeRoomStore_test.js @@ -305,16 +305,17 @@ describe("loop.store.ActiveRoomStore", f var fakeToken, fakeRoomData; beforeEach(function() { fakeToken = "337-ff-54"; fakeRoomData = { decryptedContext: { roomName: "Monkeys" }, + participants: [], roomUrl: "http://invalid" }; store = new loop.store.ActiveRoomStore(dispatcher, { mozLoop: fakeMozLoop, sdkDriver: {} }); fakeMozLoop.rooms.get.withArgs(fakeToken).callsArgOnWith( @@ -345,16 +346,17 @@ describe("loop.store.ActiveRoomStore", f roomToken: fakeToken })); sinon.assert.calledTwice(dispatcher.dispatch); sinon.assert.calledWithExactly(dispatcher.dispatch, new sharedActions.SetupRoomInfo({ roomContextUrls: undefined, roomDescription: undefined, + participants: [], roomToken: fakeToken, roomName: fakeRoomData.decryptedContext.roomName, roomUrl: fakeRoomData.roomUrl, socialShareProviders: [] })); }); it("should dispatch a JoinRoom action if the get is successful", @@ -1272,16 +1274,40 @@ describe("loop.store.ActiveRoomStore", f store.setStoreState({ remoteSrcVideoObject: { name: "fakeVideoElement" } }); store.remotePeerDisconnected(); expect(store.getStoreState().remoteSrcVideoObject).eql(null); }); + + it("should remove non-owner participants", function() { + store.setStoreState({ + participants: [{owner: true}, {}] + }); + + store.remotePeerDisconnected(); + + var participants = store.getStoreState().participants; + expect(participants).to.have.length.of(1); + expect(participants[0].owner).eql(true); + }); + + it("should keep the owner participant", function() { + store.setStoreState({ + participants: [{owner: true}] + }); + + store.remotePeerDisconnected(); + + var participants = store.getStoreState().participants; + expect(participants).to.have.length.of(1); + expect(participants[0].owner).eql(true); + }); }); describe("#connectionStatus", function() { it("should call rooms.sendConnectionStatus on mozLoop", function() { store.setStoreState({ roomToken: "fakeToken", sessionToken: "9876543210" }); @@ -1513,16 +1539,17 @@ describe("loop.store.ActiveRoomStore", f }; fakeMozLoop.rooms.on.callArgWith(1, "update", fakeRoomData); sinon.assert.calledOnce(dispatcher.dispatch); sinon.assert.calledWithExactly(dispatcher.dispatch, new sharedActions.UpdateRoomInfo({ description: "fakeDescription", + participants: undefined, roomName: fakeRoomData.decryptedContext.roomName, roomUrl: fakeRoomData.roomUrl, urls: { fake: "url" } })); });