Bug 1088672 - Part 1. Rewrite Loop's incoming call handling in the flux style. Rename some views for better naming. r=mikedeboer
authorMark Banner <standard8@mozilla.com>
Thu, 12 Mar 2015 14:01:37 +0000
changeset 233265 624232e720c8a02ca1fce1e65d9a1dfeaa3de259
parent 233264 edc1012c711b78dad70636fa924f8ab57e13e695
child 233266 8119c5b062538430dafae8a289b418294225668d
push id28409
push userryanvm@gmail.com
push dateThu, 12 Mar 2015 21:55:43 +0000
treeherdermozilla-central@849053cb635d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmikedeboer
bugs1088672
milestone39.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
Bug 1088672 - Part 1. Rewrite Loop's incoming call handling in the flux style. Rename some views for better naming. r=mikedeboer
browser/components/loop/content/js/conversation.js
browser/components/loop/content/js/conversation.jsx
browser/components/loop/content/js/conversationViews.js
browser/components/loop/content/js/conversationViews.jsx
browser/components/loop/test/desktop-local/conversationViews_test.js
browser/components/loop/test/desktop-local/conversation_test.js
--- a/browser/components/loop/content/js/conversation.js
+++ b/browser/components/loop/content/js/conversation.js
@@ -12,17 +12,17 @@ loop.conversation = (function(mozL10n) {
   "use strict";
 
   var sharedViews = loop.shared.views;
   var sharedMixins = loop.shared.mixins;
   var sharedModels = loop.shared.models;
   var sharedActions = loop.shared.actions;
 
   var IncomingConversationView = loop.conversationViews.IncomingConversationView;
-  var OutgoingConversationView = loop.conversationViews.OutgoingConversationView;
+  var CallControllerView = loop.conversationViews.CallControllerView;
   var CallIdentifierView = loop.conversationViews.CallIdentifierView;
   var DesktopRoomConversationView = loop.roomViews.DesktopRoomConversationView;
   var GenericFailureView = loop.conversationViews.GenericFailureView;
 
   /**
    * Master controller view for handling if incoming or outgoing calls are
    * in progress, and hence, which view to display.
    */
@@ -56,17 +56,17 @@ loop.conversation = (function(mozL10n) {
             client: this.props.client, 
             conversation: this.props.conversation, 
             sdk: this.props.sdk, 
             isDesktop: true, 
             conversationAppStore: this.getStore()}
           ));
         }
         case "outgoing": {
-          return (React.createElement(OutgoingConversationView, {
+          return (React.createElement(CallControllerView, {
             dispatcher: this.props.dispatcher}
           ));
         }
         case "room": {
           return (React.createElement(DesktopRoomConversationView, {
             dispatcher: this.props.dispatcher, 
             roomStore: this.props.roomStore}
           ));
--- a/browser/components/loop/content/js/conversation.jsx
+++ b/browser/components/loop/content/js/conversation.jsx
@@ -12,17 +12,17 @@ loop.conversation = (function(mozL10n) {
   "use strict";
 
   var sharedViews = loop.shared.views;
   var sharedMixins = loop.shared.mixins;
   var sharedModels = loop.shared.models;
   var sharedActions = loop.shared.actions;
 
   var IncomingConversationView = loop.conversationViews.IncomingConversationView;
-  var OutgoingConversationView = loop.conversationViews.OutgoingConversationView;
+  var CallControllerView = loop.conversationViews.CallControllerView;
   var CallIdentifierView = loop.conversationViews.CallIdentifierView;
   var DesktopRoomConversationView = loop.roomViews.DesktopRoomConversationView;
   var GenericFailureView = loop.conversationViews.GenericFailureView;
 
   /**
    * Master controller view for handling if incoming or outgoing calls are
    * in progress, and hence, which view to display.
    */
@@ -56,17 +56,17 @@ loop.conversation = (function(mozL10n) {
             client={this.props.client}
             conversation={this.props.conversation}
             sdk={this.props.sdk}
             isDesktop={true}
             conversationAppStore={this.getStore()}
           />);
         }
         case "outgoing": {
-          return (<OutgoingConversationView
+          return (<CallControllerView
             dispatcher={this.props.dispatcher}
           />);
         }
         case "room": {
           return (<DesktopRoomConversationView
             dispatcher={this.props.dispatcher}
             roomStore={this.props.roomStore}
           />);
--- a/browser/components/loop/content/js/conversationViews.js
+++ b/browser/components/loop/content/js/conversationViews.js
@@ -135,17 +135,17 @@ loop.conversationViews = (function(mozL1
         )
       );
     }
   });
 
   // Matches strings of the form "<nonspaces>@<nonspaces>" or "+<digits>"
   var EMAIL_OR_PHONE_RE = /^(:?\S+@\S+|\+\d+)$/;
 
-  var IncomingCallView = React.createClass({displayName: "IncomingCallView",
+  var AcceptCallView = React.createClass({displayName: "AcceptCallView",
     mixins: [sharedMixins.DropdownMenuMixin, sharedMixins.AudioMixin],
 
     propTypes: {
       model: React.PropTypes.object.isRequired,
       video: React.PropTypes.bool.isRequired
     },
 
     getDefaultProps: function() {
@@ -392,17 +392,17 @@ loop.conversationViews = (function(mozL1
           // XXX Don't render anything initially, though this should probably
           // be some sort of pending view, whilst we connect the websocket.
           return null;
         }
         case "incoming": {
           document.title = mozL10n.get("incoming_call_title2");
 
           return (
-            React.createElement(IncomingCallView, {
+            React.createElement(AcceptCallView, {
               model: this.props.conversation, 
               video: this.props.conversation.hasVideoStream("incoming")}
             )
           );
         }
         case "connected": {
           document.title = this.props.conversation.getCallIdentifier();
 
@@ -919,17 +919,17 @@ loop.conversationViews = (function(mozL1
       );
     }
   });
 
   /**
    * Master View Controller for outgoing calls. This manages
    * the different views that need displaying.
    */
-  var OutgoingConversationView = React.createClass({displayName: "OutgoingConversationView",
+  var CallControllerView = React.createClass({displayName: "CallControllerView",
     mixins: [
       sharedMixins.AudioMixin,
       loop.store.StoreMixin("conversationStore"),
       Backbone.Events
     ],
 
     propTypes: {
       dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired
@@ -1006,15 +1006,15 @@ loop.conversationViews = (function(mozL1
 
   return {
     PendingConversationView: PendingConversationView,
     CallIdentifierView: CallIdentifierView,
     ConversationDetailView: ConversationDetailView,
     CallFailedView: CallFailedView,
     _getContactDisplayName: _getContactDisplayName,
     GenericFailureView: GenericFailureView,
-    IncomingCallView: IncomingCallView,
+    AcceptCallView: AcceptCallView,
     IncomingConversationView: IncomingConversationView,
     OngoingConversationView: OngoingConversationView,
-    OutgoingConversationView: OutgoingConversationView
+    CallControllerView: CallControllerView
   };
 
 })(document.mozL10n || navigator.mozL10n);
--- a/browser/components/loop/content/js/conversationViews.jsx
+++ b/browser/components/loop/content/js/conversationViews.jsx
@@ -135,17 +135,17 @@ loop.conversationViews = (function(mozL1
         </div>
       );
     }
   });
 
   // Matches strings of the form "<nonspaces>@<nonspaces>" or "+<digits>"
   var EMAIL_OR_PHONE_RE = /^(:?\S+@\S+|\+\d+)$/;
 
-  var IncomingCallView = React.createClass({
+  var AcceptCallView = React.createClass({
     mixins: [sharedMixins.DropdownMenuMixin, sharedMixins.AudioMixin],
 
     propTypes: {
       model: React.PropTypes.object.isRequired,
       video: React.PropTypes.bool.isRequired
     },
 
     getDefaultProps: function() {
@@ -392,17 +392,17 @@ loop.conversationViews = (function(mozL1
           // XXX Don't render anything initially, though this should probably
           // be some sort of pending view, whilst we connect the websocket.
           return null;
         }
         case "incoming": {
           document.title = mozL10n.get("incoming_call_title2");
 
           return (
-            <IncomingCallView
+            <AcceptCallView
               model={this.props.conversation}
               video={this.props.conversation.hasVideoStream("incoming")}
             />
           );
         }
         case "connected": {
           document.title = this.props.conversation.getCallIdentifier();
 
@@ -919,17 +919,17 @@ loop.conversationViews = (function(mozL1
       );
     }
   });
 
   /**
    * Master View Controller for outgoing calls. This manages
    * the different views that need displaying.
    */
-  var OutgoingConversationView = React.createClass({
+  var CallControllerView = React.createClass({
     mixins: [
       sharedMixins.AudioMixin,
       loop.store.StoreMixin("conversationStore"),
       Backbone.Events
     ],
 
     propTypes: {
       dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired
@@ -1006,15 +1006,15 @@ loop.conversationViews = (function(mozL1
 
   return {
     PendingConversationView: PendingConversationView,
     CallIdentifierView: CallIdentifierView,
     ConversationDetailView: ConversationDetailView,
     CallFailedView: CallFailedView,
     _getContactDisplayName: _getContactDisplayName,
     GenericFailureView: GenericFailureView,
-    IncomingCallView: IncomingCallView,
+    AcceptCallView: AcceptCallView,
     IncomingConversationView: IncomingConversationView,
     OngoingConversationView: OngoingConversationView,
-    OutgoingConversationView: OutgoingConversationView
+    CallControllerView: CallControllerView
   };
 
 })(document.mozL10n || navigator.mozL10n);
--- a/browser/components/loop/test/desktop-local/conversationViews_test.js
+++ b/browser/components/loop/test/desktop-local/conversationViews_test.js
@@ -573,22 +573,22 @@ describe("loop.conversationViews", funct
       });
 
       var muteBtn = view.getDOMNode().querySelector('.btn-mute-audio');
 
       expect(muteBtn.classList.contains("muted")).eql(true);
     });
   });
 
-  describe("OutgoingConversationView", function() {
+  describe("CallControllerView", function() {
     var store, feedbackStore;
 
     function mountTestComponent() {
       return TestUtils.renderIntoDocument(
-        React.createElement(loop.conversationViews.OutgoingConversationView, {
+        React.createElement(loop.conversationViews.CallControllerView, {
           dispatcher: dispatcher,
         }));
     }
 
     beforeEach(function() {
       store = new loop.store.ConversationStore(dispatcher, {
         client: {},
         mozLoop: fakeMozLoop,
@@ -751,17 +751,17 @@ describe("loop.conversationViews", funct
           progressURL:    "http://progress.example.com",
           websocketToken: "7b"
         };
 
         conversationAppStore.setStoreState({
           windowData: fakeSessionData
         });
 
-        stubComponent(loop.conversationViews, "IncomingCallView");
+        stubComponent(loop.conversationViews, "AcceptCallView");
         stubComponent(sharedView, "ConversationView");
       });
 
       it("should start alerting", function() {
         icView = mountTestComponent();
 
         sinon.assert.calledOnce(navigator.mozLoop.startAlerting);
       });
@@ -1201,17 +1201,17 @@ describe("loop.conversationViews", funct
 
               sinon.assert.calledOnce(icView._websocket.mediaUp);
             });
         });
       });
     });
   });
 
-  describe("IncomingCallView", function() {
+  describe("AcceptCallView", function() {
     var view, model, fakeAudio;
 
     beforeEach(function() {
       var Model = Backbone.Model.extend({
         getCallIdentifier: function() {return "fakeId";}
       });
       model = new Model();
       sandbox.spy(model, "trigger");
@@ -1220,67 +1220,67 @@ describe("loop.conversationViews", funct
       fakeAudio = {
         play: sinon.spy(),
         pause: sinon.spy(),
         removeAttribute: sinon.spy()
       };
       sandbox.stub(window, "Audio").returns(fakeAudio);
 
       view = TestUtils.renderIntoDocument(
-        React.createElement(loop.conversationViews.IncomingCallView, {
+        React.createElement(loop.conversationViews.AcceptCallView, {
           model: model,
           video: true
         }));
     });
 
     describe("default answer mode", function() {
       it("should display video as primary answer mode", function() {
         view = TestUtils.renderIntoDocument(
-          React.createElement(loop.conversationViews.IncomingCallView, {
+          React.createElement(loop.conversationViews.AcceptCallView, {
             model: model,
             video: true
           }));
         var primaryBtn = view.getDOMNode()
                                   .querySelector('.fx-embedded-btn-icon-video');
 
         expect(primaryBtn).not.to.eql(null);
       });
 
       it("should display audio as primary answer mode", function() {
         view = TestUtils.renderIntoDocument(
-          React.createElement(loop.conversationViews.IncomingCallView, {
+          React.createElement(loop.conversationViews.AcceptCallView, {
             model: model,
             video: false
           }));
         var primaryBtn = view.getDOMNode()
                                   .querySelector('.fx-embedded-btn-icon-audio');
 
         expect(primaryBtn).not.to.eql(null);
       });
 
       it("should accept call with video", function() {
         view = TestUtils.renderIntoDocument(
-          React.createElement(loop.conversationViews.IncomingCallView, {
+          React.createElement(loop.conversationViews.AcceptCallView, {
             model: model,
             video: true
           }));
         var primaryBtn = view.getDOMNode()
                                   .querySelector('.fx-embedded-btn-icon-video');
 
         React.addons.TestUtils.Simulate.click(primaryBtn);
 
         sinon.assert.calledOnce(model.set);
         sinon.assert.calledWithExactly(model.set, "selectedCallType", "audio-video");
         sinon.assert.calledOnce(model.trigger);
         sinon.assert.calledWithExactly(model.trigger, "accept");
       });
 
       it("should accept call with audio", function() {
         view = TestUtils.renderIntoDocument(
-          React.createElement(loop.conversationViews.IncomingCallView, {
+          React.createElement(loop.conversationViews.AcceptCallView, {
             model: model,
             video: false
           }));
         var primaryBtn = view.getDOMNode()
                                   .querySelector('.fx-embedded-btn-icon-audio');
 
         React.addons.TestUtils.Simulate.click(primaryBtn);
 
@@ -1288,17 +1288,17 @@ describe("loop.conversationViews", funct
         sinon.assert.calledWithExactly(model.set, "selectedCallType", "audio");
         sinon.assert.calledOnce(model.trigger);
         sinon.assert.calledWithExactly(model.trigger, "accept");
       });
 
       it("should accept call with video when clicking on secondary btn",
          function() {
           view = TestUtils.renderIntoDocument(
-            React.createElement(loop.conversationViews.IncomingCallView, {
+            React.createElement(loop.conversationViews.AcceptCallView, {
               model: model,
               video: false
             }));
           var secondaryBtn = view.getDOMNode()
           .querySelector('.fx-embedded-btn-video-small');
 
           React.addons.TestUtils.Simulate.click(secondaryBtn);
 
@@ -1306,17 +1306,17 @@ describe("loop.conversationViews", funct
           sinon.assert.calledWithExactly(model.set, "selectedCallType", "audio-video");
           sinon.assert.calledOnce(model.trigger);
           sinon.assert.calledWithExactly(model.trigger, "accept");
          });
 
       it("should accept call with audio when clicking on secondary btn",
          function() {
           view = TestUtils.renderIntoDocument(
-            React.createElement(loop.conversationViews.IncomingCallView, {
+            React.createElement(loop.conversationViews.AcceptCallView, {
               model: model,
               video: true
             }));
           var secondaryBtn = view.getDOMNode()
           .querySelector('.fx-embedded-btn-audio-small');
 
           React.addons.TestUtils.Simulate.click(secondaryBtn);
 
--- a/browser/components/loop/test/desktop-local/conversation_test.js
+++ b/browser/components/loop/test/desktop-local/conversation_test.js
@@ -181,23 +181,23 @@ describe("loop.conversation", function()
       });
     });
 
     afterEach(function() {
       ccView = undefined;
       document.title = oldTitle;
     });
 
-    it("should display the OutgoingConversationView for outgoing calls", function() {
+    it("should display the CallControllerView for outgoing calls", function() {
       conversationAppStore.setStoreState({windowType: "outgoing"});
 
       ccView = mountTestComponent();
 
       TestUtils.findRenderedComponentWithType(ccView,
-        loop.conversationViews.OutgoingConversationView);
+        loop.conversationViews.CallControllerView);
     });
 
     it("should display the IncomingConversationView for incoming calls", function() {
       sandbox.stub(conversation, "setIncomingSessionData");
       sandbox.stub(loop, "CallConnectionWebSocket").returns({
         promiseConnect: function() {
           return new Promise(function() {});
         },