Bug 1074707 - Add notifications when the room is empty on Loop standalone. r=Standard8 a=loop-only
authorNicolas Perriault <nperriault@gmail.com>
Wed, 12 Nov 2014 20:59:04 +0000
changeset 233924 0a106e69eaa639b3ccb204786a6fbd6cedd04f26
parent 233923 555f6f98a7db5057617889be83c4b0bdabed8f9d
child 233925 e48ee58c73e75dba84cf663113065f813595cdb7
push id4187
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:29:12 +0000
treeherdermozilla-beta@f23cc6a30c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersStandard8, loop-only
bugs1074707
milestone35.0a2
Bug 1074707 - Add notifications when the room is empty on Loop standalone. r=Standard8 a=loop-only
browser/components/loop/content/shared/css/conversation.css
browser/components/loop/standalone/content/js/standaloneRoomViews.js
browser/components/loop/standalone/content/js/standaloneRoomViews.jsx
browser/components/loop/test/standalone/standaloneRoomViews_test.js
browser/components/loop/ui/ui-showcase.js
browser/components/loop/ui/ui-showcase.jsx
--- a/browser/components/loop/content/shared/css/conversation.css
+++ b/browser/components/loop/content/shared/css/conversation.css
@@ -738,26 +738,29 @@ html, .fx-embedded, #main,
 }
 
 /* Standalone rooms */
 
 .standalone .room-conversation-wrapper {
   position: relative;
 }
 
-.standalone .room-inner-action-area {
+.standalone .room-inner-info-area {
   position: absolute;
   top: 35%;
+  left: 0;
+  right: 25%;
   z-index: 1000;
   margin: 0 auto;
   width: 50%;
+  color: #fff;
+  font-weight: bold;
 }
 
-.standalone .room-inner-action-area button {
-  position: absolute;
+.standalone .room-inner-info-area button {
   border-radius: 3px;
   font-size: 1.2em;
   padding: .2em 1.2em;
   cursor: pointer;
 }
 
 .standalone .room-conversation h2.room-name {
   position: absolute;
--- a/browser/components/loop/standalone/content/js/standaloneRoomViews.js
+++ b/browser/components/loop/standalone/content/js/standaloneRoomViews.js
@@ -124,42 +124,56 @@ loop.standaloneRoomViews = (function(moz
      * @return {Boolean}
      */
     _roomIsActive: function() {
       return this.state.roomState === ROOM_STATES.JOINED            ||
              this.state.roomState === ROOM_STATES.SESSION_CONNECTED ||
              this.state.roomState === ROOM_STATES.HAS_PARTICIPANTS;
     },
 
-    _renderActionButtons: function() {
+    _renderContextualRoomInfo: function() {
+      switch(this.state.roomState) {
+        case ROOM_STATES.INIT:
+        case ROOM_STATES.READY: {
+          // Join button
+          return (
+            React.DOM.div({className: "room-inner-info-area"}, 
+              React.DOM.button({className: "btn btn-join btn-info", onClick: this.joinRoom}, 
+                mozL10n.get("rooms_room_join_label")
+              )
+            )
+          );
+        }
+        case ROOM_STATES.JOINED:
+        case ROOM_STATES.SESSION_CONNECTED: {
+          // Empty room message
+          return (
+            React.DOM.div({className: "room-inner-info-area"}, 
+              React.DOM.p({className: "empty-room-message"}, 
+                mozL10n.get("rooms_only_occupant_label")
+              )
+            )
+          );
+        }
+      }
       // XXX Render "Start your own" button when room is over capacity (see
       //     bug 1074709)
-      if (this.state.roomState === ROOM_STATES.INIT ||
-          this.state.roomState === ROOM_STATES.READY) {
-        return (
-          React.DOM.div({className: "room-inner-action-area"}, 
-            React.DOM.button({className: "btn btn-join btn-info", onClick: this.joinRoom}, 
-              mozL10n.get("rooms_room_join_label")
-            )
-          )
-        );
-      }
     },
 
     render: function() {
       var localStreamClasses = React.addons.classSet({
         hide: !this._roomIsActive(),
         local: true,
         "local-stream": true,
         "local-stream-audio": false
       });
 
       return (
         React.DOM.div({className: "room-conversation-wrapper"}, 
-          this._renderActionButtons(), 
+          this._renderContextualRoomInfo(), 
           React.DOM.div({className: "video-layout-wrapper"}, 
             React.DOM.div({className: "conversation room-conversation"}, 
               React.DOM.h2({className: "room-name"}, this.state.roomName), 
               React.DOM.div({className: "media nested"}, 
                 React.DOM.div({className: "video_wrapper remote_wrapper"}, 
                   React.DOM.div({className: "video_inner remote"})
                 ), 
                 React.DOM.div({className: localStreamClasses})
--- a/browser/components/loop/standalone/content/js/standaloneRoomViews.jsx
+++ b/browser/components/loop/standalone/content/js/standaloneRoomViews.jsx
@@ -124,42 +124,56 @@ loop.standaloneRoomViews = (function(moz
      * @return {Boolean}
      */
     _roomIsActive: function() {
       return this.state.roomState === ROOM_STATES.JOINED            ||
              this.state.roomState === ROOM_STATES.SESSION_CONNECTED ||
              this.state.roomState === ROOM_STATES.HAS_PARTICIPANTS;
     },
 
-    _renderActionButtons: function() {
+    _renderContextualRoomInfo: function() {
+      switch(this.state.roomState) {
+        case ROOM_STATES.INIT:
+        case ROOM_STATES.READY: {
+          // Join button
+          return (
+            <div className="room-inner-info-area">
+              <button className="btn btn-join btn-info" onClick={this.joinRoom}>
+                {mozL10n.get("rooms_room_join_label")}
+              </button>
+            </div>
+          );
+        }
+        case ROOM_STATES.JOINED:
+        case ROOM_STATES.SESSION_CONNECTED: {
+          // Empty room message
+          return (
+            <div className="room-inner-info-area">
+              <p className="empty-room-message">
+                {mozL10n.get("rooms_only_occupant_label")}
+              </p>
+            </div>
+          );
+        }
+      }
       // XXX Render "Start your own" button when room is over capacity (see
       //     bug 1074709)
-      if (this.state.roomState === ROOM_STATES.INIT ||
-          this.state.roomState === ROOM_STATES.READY) {
-        return (
-          <div className="room-inner-action-area">
-            <button className="btn btn-join btn-info" onClick={this.joinRoom}>
-              {mozL10n.get("rooms_room_join_label")}
-            </button>
-          </div>
-        );
-      }
     },
 
     render: function() {
       var localStreamClasses = React.addons.classSet({
         hide: !this._roomIsActive(),
         local: true,
         "local-stream": true,
         "local-stream-audio": false
       });
 
       return (
         <div className="room-conversation-wrapper">
-          {this._renderActionButtons()}
+          {this._renderContextualRoomInfo()}
           <div className="video-layout-wrapper">
             <div className="conversation room-conversation">
               <h2 className="room-name">{this.state.roomName}</h2>
               <div className="media nested">
                 <div className="video_wrapper remote_wrapper">
                   <div className="video_inner remote"></div>
                 </div>
                 <div className={localStreamClasses}></div>
--- a/browser/components/loop/test/standalone/standaloneRoomViews_test.js
+++ b/browser/components/loop/test/standalone/standaloneRoomViews_test.js
@@ -97,16 +97,42 @@ describe("loop.standaloneRoomViews", fun
 
     describe("#render", function() {
       var view;
 
       beforeEach(function() {
         view = mountTestComponent();
       });
 
+      describe("Empty room message", function() {
+        it("should display an empty room message on JOINED",
+          function() {
+            activeRoomStore.setStoreState({roomState: ROOM_STATES.JOINED});
+
+            expect(view.getDOMNode().querySelector(".empty-room-message"))
+              .not.eql(null);
+          });
+
+        it("should display an empty room message on SESSION_CONNECTED",
+          function() {
+            activeRoomStore.setStoreState({roomState: ROOM_STATES.SESSION_CONNECTED});
+
+            expect(view.getDOMNode().querySelector(".empty-room-message"))
+              .not.eql(null);
+          });
+
+        it("shouldn't display an empty room message on HAS_PARTICIPANTS",
+          function() {
+            activeRoomStore.setStoreState({roomState: ROOM_STATES.HAS_PARTICIPANTS});
+
+            expect(view.getDOMNode().querySelector(".empty-room-message"))
+              .eql(null);
+          });
+      });
+
       describe("Join button", function() {
         function getJoinButton(view) {
           return view.getDOMNode().querySelector(".btn-join");
         }
 
         it("should render the Join button when room isn't active", function() {
           activeRoomStore.setStoreState({roomState: ROOM_STATES.READY});
 
--- a/browser/components/loop/ui/ui-showcase.js
+++ b/browser/components/loop/ui/ui-showcase.js
@@ -564,16 +564,25 @@
               React.DOM.div({className: "standalone"}, 
                 StandaloneRoomView({
                   dispatcher: dispatcher, 
                   activeRoomStore: activeRoomStore, 
                   roomState: ROOM_STATES.READY})
               )
             ), 
 
+            Example({summary: "Standalone room conversation (joined)"}, 
+              React.DOM.div({className: "standalone"}, 
+                StandaloneRoomView({
+                  dispatcher: dispatcher, 
+                  activeRoomStore: activeRoomStore, 
+                  roomState: ROOM_STATES.JOINED})
+              )
+            ), 
+
             Example({summary: "Standalone room conversation (has-participants)"}, 
               React.DOM.div({className: "standalone"}, 
                 StandaloneRoomView({
                   dispatcher: dispatcher, 
                   activeRoomStore: activeRoomStore, 
                   roomState: ROOM_STATES.HAS_PARTICIPANTS})
               )
             )
--- a/browser/components/loop/ui/ui-showcase.jsx
+++ b/browser/components/loop/ui/ui-showcase.jsx
@@ -564,16 +564,25 @@
               <div className="standalone">
                 <StandaloneRoomView
                   dispatcher={dispatcher}
                   activeRoomStore={activeRoomStore}
                   roomState={ROOM_STATES.READY} />
               </div>
             </Example>
 
+            <Example summary="Standalone room conversation (joined)">
+              <div className="standalone">
+                <StandaloneRoomView
+                  dispatcher={dispatcher}
+                  activeRoomStore={activeRoomStore}
+                  roomState={ROOM_STATES.JOINED} />
+              </div>
+            </Example>
+
             <Example summary="Standalone room conversation (has-participants)">
               <div className="standalone">
                 <StandaloneRoomView
                   dispatcher={dispatcher}
                   activeRoomStore={activeRoomStore}
                   roomState={ROOM_STATES.HAS_PARTICIPANTS} />
               </div>
             </Example>