Bug 1097743 - Part 1: Loop standalone styling enhancements. r=Standard8
authorNicolas Perriault <nperriault@gmail.com>
Thu, 13 Nov 2014 22:45:23 +0000
changeset 215746 100301b84f5f15a794a2f5c50b87e84e2079728d
parent 215745 8f4f59d06ef12a8ecb8a45f2ae770781c0d06955
child 215747 bd6aae177d9c470dbdc219ee78a9c7f06b12ac1d
push id51845
push usercbook@mozilla.com
push dateFri, 14 Nov 2014 12:23:21 +0000
treeherdermozilla-inbound@da57927b609d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersStandard8
bugs1097743
milestone36.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 1097743 - Part 1: Loop standalone styling enhancements. r=Standard8
browser/components/loop/content/shared/css/conversation.css
browser/components/loop/standalone/content/css/webapp.css
browser/components/loop/standalone/content/js/standaloneRoomViews.js
browser/components/loop/standalone/content/js/standaloneRoomViews.jsx
--- a/browser/components/loop/content/shared/css/conversation.css
+++ b/browser/components/loop/content/shared/css/conversation.css
@@ -692,16 +692,48 @@ html, .fx-embedded, #main,
  * Rooms
  */
 
 .room-conversation-wrapper {
   position: relative;
   height: 100%;
 }
 
+.standalone .room-conversation-wrapper {
+  height: calc(100% - 50px - 60px);
+  background: #000;
+}
+
+.room-conversation-wrapper header {
+  background: #000;
+  height: 50px;
+  text-align: left;
+}
+
+.room-conversation-wrapper header h1 {
+  font-size: 1.5em;
+  color: #fff;
+  line-height: 50px;
+  text-indent: 50px;
+  background-image: url("../img/firefox-logo.png");
+  background-size: 30px;
+  background-position: 10px;
+  background-repeat: no-repeat;
+}
+
+.room-conversation-wrapper footer {
+  background: #000;
+  height: 60px;
+  margin-top: -12px;
+}
+
+.room-conversation-wrapper footer a {
+  color: #555;
+}
+
 /**
  * Hides the hangup button for room conversations.
  */
 .room-conversation .conversation-toolbar .btn-hangup-entry {
   display: none;
 }
 
 .room-invitation-overlay {
@@ -740,17 +772,17 @@ html, .fx-embedded, #main,
 /* Standalone rooms */
 
 .standalone .room-conversation-wrapper {
   position: relative;
 }
 
 .standalone .room-inner-info-area {
   position: absolute;
-  top: 35%;
+  top: 50%;
   left: 0;
   right: 25%;
   z-index: 1000;
   margin: 0 auto;
   width: 50%;
   color: #fff;
   font-weight: bold;
   font-size: 1.1em;
@@ -762,16 +794,17 @@ html, .fx-embedded, #main,
   padding: .2em 1.2em;
   cursor: pointer;
 }
 
 .standalone .room-inner-info-area a.btn {
   padding: .5em 3em .3em 3em;
   border-radius: 3px;
   font-weight: normal;
+  max-width: 400px;
 }
 
 .standalone .room-conversation h2.room-name {
   position: absolute;
   display: inline-block;
   top: 0;
   right: 0;
   color: #fff;
@@ -791,14 +824,14 @@ html, .fx-embedded, #main,
 
 .standalone .room-conversation .local-stream {
   width: 33%;
   height: 26.5%;
 }
 
 .standalone .room-conversation .conversation-toolbar {
   background: #000;
-  border-top: none;
+  border: none;
 }
 
 .standalone .room-conversation .conversation-toolbar .btn-hangup-entry {
   display: block;
 }
--- a/browser/components/loop/standalone/content/css/webapp.css
+++ b/browser/components/loop/standalone/content/css/webapp.css
@@ -13,16 +13,23 @@ body,
 .standalone {
   width: 100%;
   background: #fbfbfb;
   color: #666;
   text-align: center;
   font-family: Open Sans,sans-serif;
 }
 
+/**
+ * Note: the is-standalone-room class is dynamically set by the StandaloneRoomView.
+ */
+.standalone.is-standalone-room {
+  background-color: #000;
+}
+
 .standalone-header {
   border-radius: 4px;
   background: #fff;
   border: 1px solid #E7E7E7;
   box-shadow: 0px 2px 0px rgba(0, 0, 0, 0.03);
   background-image: url("../shared/img/beta-ribbon.svg#beta-ribbon");
   background-size: 5rem 5rem;
   background-repeat: no-repeat;
--- a/browser/components/loop/standalone/content/js/standaloneRoomViews.js
+++ b/browser/components/loop/standalone/content/js/standaloneRoomViews.js
@@ -8,16 +8,17 @@
 /* jshint newcap:false, maxlen:false */
 
 var loop = loop || {};
 loop.standaloneRoomViews = (function(mozL10n) {
   "use strict";
 
   var ROOM_STATES = loop.store.ROOM_STATES;
   var sharedActions = loop.shared.actions;
+  var sharedMixins = loop.shared.mixins;
   var sharedViews = loop.shared.views;
 
   var StandaloneRoomInfoArea = React.createClass({displayName: 'StandaloneRoomInfoArea',
     propTypes: {
       helper: React.PropTypes.instanceOf(loop.shared.utils.Helper).isRequired
     },
 
     _renderCallToActionLink: function() {
@@ -76,16 +77,53 @@ loop.standaloneRoomViews = (function(moz
       return (
         React.DOM.div({className: "room-inner-info-area"}, 
           this._renderContent()
         )
       );
     }
   });
 
+  var StandaloneRoomHeader = React.createClass({displayName: 'StandaloneRoomHeader',
+    render: function() {
+      return (
+        React.DOM.header(null, 
+          React.DOM.h1(null, mozL10n.get("clientShortname2"))
+        )
+      );
+    }
+  });
+
+  var StandaloneRoomFooter = React.createClass({displayName: 'StandaloneRoomFooter',
+    _getContent: function() {
+      return mozL10n.get("legal_text_and_links", {
+        "clientShortname": mozL10n.get("clientShortname2"),
+        "terms_of_use_url": React.renderComponentToStaticMarkup(
+          React.DOM.a({href: loop.config.legalWebsiteUrl, target: "_blank"}, 
+            mozL10n.get("terms_of_use_link_text")
+          )
+        ),
+        "privacy_notice_url": React.renderComponentToStaticMarkup(
+          React.DOM.a({href: loop.config.privacyWebsiteUrl, target: "_blank"}, 
+            mozL10n.get("privacy_notice_link_text")
+          )
+        ),
+      });
+    },
+
+    render: function() {
+      return (
+        React.DOM.footer(null, 
+          React.DOM.p({dangerouslySetInnerHTML: {__html: this._getContent()}}), 
+          React.DOM.div({className: "footer-logo"})
+        )
+      );
+    }
+  });
+
   var StandaloneRoomView = React.createClass({displayName: 'StandaloneRoomView',
     mixins: [Backbone.Events],
 
     propTypes: {
       activeRoomStore:
         React.PropTypes.instanceOf(loop.store.ActiveRoomStore).isRequired,
       dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
       helper: React.PropTypes.instanceOf(loop.shared.utils.Helper).isRequired
@@ -139,16 +177,21 @@ loop.standaloneRoomViews = (function(moz
           bugDisplayMode: "off",
           buttonDisplayMode: "off",
           nameDisplayMode: "off",
           videoDisabledDisplayMode: "off"
         }
       };
     },
 
+    componentDidMount: function() {
+      // Adding a class to the document body element from here to ease styling it.
+      document.body.classList.add("is-standalone-room");
+    },
+
     componentWillUnmount: function() {
       this.stopListening(this.props.activeRoomStore);
     },
 
     /**
      * Watches for when we transition from READY to JOINED room state, so we can
      * request user media access.
      * @param  {Object} nextProps (Unused)
@@ -202,16 +245,17 @@ loop.standaloneRoomViews = (function(moz
         hide: !this._roomIsActive(),
         local: true,
         "local-stream": true,
         "local-stream-audio": false
       });
 
       return (
         React.DOM.div({className: "room-conversation-wrapper"}, 
+          StandaloneRoomHeader(null), 
           StandaloneRoomInfoArea({roomState: this.state.roomState, 
                                   joinRoom: this.joinRoom, 
                                   helper: this.props.helper}), 
           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"}, 
@@ -224,17 +268,18 @@ loop.standaloneRoomViews = (function(moz
                         visible: this._roomIsActive()}, 
                 audio: {enabled: !this.state.audioMuted,
                         visible: this._roomIsActive()}, 
                 publishStream: this.publishStream, 
                 hangup: this.leaveRoom, 
                 hangupButtonLabel: mozL10n.get("rooms_leave_button_label"), 
                 enableHangup: this._roomIsActive()})
             )
-          )
+          ), 
+          StandaloneRoomFooter(null)
         )
       );
     }
   });
 
   return {
     StandaloneRoomView: StandaloneRoomView
   };
--- a/browser/components/loop/standalone/content/js/standaloneRoomViews.jsx
+++ b/browser/components/loop/standalone/content/js/standaloneRoomViews.jsx
@@ -8,16 +8,17 @@
 /* jshint newcap:false, maxlen:false */
 
 var loop = loop || {};
 loop.standaloneRoomViews = (function(mozL10n) {
   "use strict";
 
   var ROOM_STATES = loop.store.ROOM_STATES;
   var sharedActions = loop.shared.actions;
+  var sharedMixins = loop.shared.mixins;
   var sharedViews = loop.shared.views;
 
   var StandaloneRoomInfoArea = React.createClass({
     propTypes: {
       helper: React.PropTypes.instanceOf(loop.shared.utils.Helper).isRequired
     },
 
     _renderCallToActionLink: function() {
@@ -76,16 +77,53 @@ loop.standaloneRoomViews = (function(moz
       return (
         <div className="room-inner-info-area">
           {this._renderContent()}
         </div>
       );
     }
   });
 
+  var StandaloneRoomHeader = React.createClass({
+    render: function() {
+      return (
+        <header>
+          <h1>{mozL10n.get("clientShortname2")}</h1>
+        </header>
+      );
+    }
+  });
+
+  var StandaloneRoomFooter = React.createClass({
+    _getContent: function() {
+      return mozL10n.get("legal_text_and_links", {
+        "clientShortname": mozL10n.get("clientShortname2"),
+        "terms_of_use_url": React.renderComponentToStaticMarkup(
+          <a href={loop.config.legalWebsiteUrl} target="_blank">
+            {mozL10n.get("terms_of_use_link_text")}
+          </a>
+        ),
+        "privacy_notice_url": React.renderComponentToStaticMarkup(
+          <a href={loop.config.privacyWebsiteUrl} target="_blank">
+            {mozL10n.get("privacy_notice_link_text")}
+          </a>
+        ),
+      });
+    },
+
+    render: function() {
+      return (
+        <footer>
+          <p dangerouslySetInnerHTML={{__html: this._getContent()}}></p>
+          <div className="footer-logo" />
+        </footer>
+      );
+    }
+  });
+
   var StandaloneRoomView = React.createClass({
     mixins: [Backbone.Events],
 
     propTypes: {
       activeRoomStore:
         React.PropTypes.instanceOf(loop.store.ActiveRoomStore).isRequired,
       dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
       helper: React.PropTypes.instanceOf(loop.shared.utils.Helper).isRequired
@@ -139,16 +177,21 @@ loop.standaloneRoomViews = (function(moz
           bugDisplayMode: "off",
           buttonDisplayMode: "off",
           nameDisplayMode: "off",
           videoDisabledDisplayMode: "off"
         }
       };
     },
 
+    componentDidMount: function() {
+      // Adding a class to the document body element from here to ease styling it.
+      document.body.classList.add("is-standalone-room");
+    },
+
     componentWillUnmount: function() {
       this.stopListening(this.props.activeRoomStore);
     },
 
     /**
      * Watches for when we transition from READY to JOINED room state, so we can
      * request user media access.
      * @param  {Object} nextProps (Unused)
@@ -202,16 +245,17 @@ loop.standaloneRoomViews = (function(moz
         hide: !this._roomIsActive(),
         local: true,
         "local-stream": true,
         "local-stream-audio": false
       });
 
       return (
         <div className="room-conversation-wrapper">
+          <StandaloneRoomHeader />
           <StandaloneRoomInfoArea roomState={this.state.roomState}
                                   joinRoom={this.joinRoom}
                                   helper={this.props.helper} />
           <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">
@@ -225,16 +269,17 @@ loop.standaloneRoomViews = (function(moz
                 audio={{enabled: !this.state.audioMuted,
                         visible: this._roomIsActive()}}
                 publishStream={this.publishStream}
                 hangup={this.leaveRoom}
                 hangupButtonLabel={mozL10n.get("rooms_leave_button_label")}
                 enableHangup={this._roomIsActive()} />
             </div>
           </div>
+          <StandaloneRoomFooter />
         </div>
       );
     }
   });
 
   return {
     StandaloneRoomView: StandaloneRoomView
   };