Bug 1184924 - Implement the refreshed design for the invitation overlay [r=Standard8]
authorEd Lee <edilee@mozilla.com>
Fri, 18 Sep 2015 10:45:47 -0700
changeset 265686 63fe244f62b8ab4b7afe560b41a8bcf1a62afcaa
parent 265685 f620ddf0e688f184a06fb3df5d8e2eda64752968
child 265687 fb34a505c11eb7eaba36002ca6a59c29bc127aba
push id66003
push usercbook@mozilla.com
push dateFri, 02 Oct 2015 11:37:40 +0000
treeherdermozilla-inbound@3fd732d24f46 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersStandard8
bugs1184924
milestone44.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 1184924 - Implement the refreshed design for the invitation overlay [r=Standard8]
browser/components/loop/content/js/roomViews.js
browser/components/loop/content/js/roomViews.jsx
browser/components/loop/content/shared/css/conversation.css
browser/components/loop/content/shared/img/svg/glyph-email-16x16.svg
browser/components/loop/content/shared/img/svg/glyph-facebook-16x16.svg
browser/components/loop/content/shared/img/svg/glyph-link-16x16.svg
browser/components/loop/content/shared/img/svg/glyph-user-16x16.svg
browser/components/loop/jar.mn
browser/components/loop/test/desktop-local/roomViews_test.js
--- a/browser/components/loop/content/js/roomViews.js
+++ b/browser/components/loop/content/js/roomViews.js
@@ -186,16 +186,20 @@ loop.roomViews = (function(mozL10n) {
       );
     }
   });
 
   /**
    * Desktop room invitation view (overlay).
    */
   var DesktopRoomInvitationView = React.createClass({displayName: "DesktopRoomInvitationView",
+    statics: {
+      TRIGGERED_RESET_DELAY: 2000
+    },
+
     mixins: [sharedMixins.DropdownMenuMixin(".room-invitation-overlay")],
 
     propTypes: {
       dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
       error: React.PropTypes.object,
       mozLoop: React.PropTypes.object.isRequired,
       onAddContextClick: React.PropTypes.func,
       onEditContextClose: React.PropTypes.func,
@@ -231,87 +235,81 @@ loop.roomViews = (function(mozL10n) {
       event.preventDefault();
 
       this.props.dispatcher.dispatch(new sharedActions.CopyRoomUrl({
         roomUrl: this.props.roomData.roomUrl,
         from: "conversation"
       }));
 
       this.setState({copiedUrl: true});
+      setTimeout(this.resetTriggeredButtons, this.constructor.TRIGGERED_RESET_DELAY);
+    },
+
+    /**
+     * Reset state of triggered buttons if necessary
+     */
+    resetTriggeredButtons: function() {
+      if (this.state.copiedUrl) {
+        this.setState({copiedUrl: false});
+      }
     },
 
     handleShareButtonClick: function(event) {
       event.preventDefault();
 
       var providers = this.props.socialShareProviders;
       // If there are no providers available currently, save a click by dispatching
       // the 'AddSocialShareProvider' right away.
       if (!providers || !providers.length) {
         this.props.dispatcher.dispatch(new sharedActions.AddSocialShareProvider());
         return;
       }
 
       this.toggleDropdownMenu();
     },
 
-    handleAddContextClick: function(event) {
-      event.preventDefault();
-
-      if (this.props.onAddContextClick) {
-        this.props.onAddContextClick();
-      }
-    },
-
     handleEditContextClose: function() {
       if (this.props.onEditContextClose) {
         this.props.onEditContextClose();
       }
     },
 
     render: function() {
       if (!this.props.show) {
         return null;
       }
 
-      var canAddContext = this.props.mozLoop.getLoopPref("contextInConversations.enabled") &&
-        // Don't show the link when we're showing the edit form already:
-        !this.props.showEditContext &&
-        // Don't show the link when there's already context data available:
-        !(this.props.roomData.roomContextUrls || this.props.roomData.roomDescription);
-
       var cx = React.addons.classSet;
       return (
         React.createElement("div", {className: "room-invitation-overlay"}, 
           React.createElement("div", {className: "room-invitation-content"}, 
             React.createElement("p", {className: cx({hide: this.props.showEditContext})}, 
-              mozL10n.get("invite_header_text")
-            ), 
-            React.createElement("a", {className: cx({hide: !canAddContext, "room-invitation-addcontext": true}), 
-               onClick: this.handleAddContextClick}, 
-              mozL10n.get("context_add_some_label")
+              mozL10n.get("invite_header_text2")
             )
           ), 
           React.createElement("div", {className: cx({
             "btn-group": true,
             "call-action-group": true,
             hide: this.props.showEditContext
           })}, 
-            React.createElement("button", {className: "btn btn-info btn-email", 
-                    onClick: this.handleEmailButtonClick}, 
-              mozL10n.get("email_link_button")
+            React.createElement("div", {className: cx({
+                "btn-copy": true,
+                "invite-button": true,
+                "triggered": this.state.copiedUrl
+              }), 
+              onClick: this.handleCopyButtonClick}, 
+              React.createElement("img", {src: "loop/shared/img/svg/glyph-link-16x16.svg"}), 
+              React.createElement("p", null, mozL10n.get("invite_copy_" +
+                (this.state.copiedUrl ? "triggered" : "button")))
             ), 
-            React.createElement("button", {className: "btn btn-info btn-copy", 
-                    onClick: this.handleCopyButtonClick}, 
-              this.state.copiedUrl ? mozL10n.get("copied_url_button") :
-                                      mozL10n.get("copy_url_button2")
-            ), 
-            React.createElement("button", {className: "btn btn-info btn-share", 
-                    onClick: this.handleShareButtonClick, 
-                    ref: "anchor"}, 
-              mozL10n.get("share_button3")
+            React.createElement("div", {className: "btn-email invite-button", 
+              onClick: this.handleEmailButtonClick, 
+              onMouseOver: this.resetTriggeredButtons}, 
+              React.createElement("img", {src: "loop/shared/img/svg/glyph-email-16x16.svg"}), 
+              React.createElement("p", null, mozL10n.get("invite_email_button"))
             )
           ), 
           React.createElement(SocialShareDropdown, {
             dispatcher: this.props.dispatcher, 
             ref: "menu", 
             roomUrl: this.props.roomData.roomUrl, 
             show: this.state.showMenu, 
             socialShareProviders: this.props.socialShareProviders}), 
--- a/browser/components/loop/content/js/roomViews.jsx
+++ b/browser/components/loop/content/js/roomViews.jsx
@@ -186,16 +186,20 @@ loop.roomViews = (function(mozL10n) {
       );
     }
   });
 
   /**
    * Desktop room invitation view (overlay).
    */
   var DesktopRoomInvitationView = React.createClass({
+    statics: {
+      TRIGGERED_RESET_DELAY: 2000
+    },
+
     mixins: [sharedMixins.DropdownMenuMixin(".room-invitation-overlay")],
 
     propTypes: {
       dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
       error: React.PropTypes.object,
       mozLoop: React.PropTypes.object.isRequired,
       onAddContextClick: React.PropTypes.func,
       onEditContextClose: React.PropTypes.func,
@@ -231,88 +235,82 @@ loop.roomViews = (function(mozL10n) {
       event.preventDefault();
 
       this.props.dispatcher.dispatch(new sharedActions.CopyRoomUrl({
         roomUrl: this.props.roomData.roomUrl,
         from: "conversation"
       }));
 
       this.setState({copiedUrl: true});
+      setTimeout(this.resetTriggeredButtons, this.constructor.TRIGGERED_RESET_DELAY);
+    },
+
+    /**
+     * Reset state of triggered buttons if necessary
+     */
+    resetTriggeredButtons: function() {
+      if (this.state.copiedUrl) {
+        this.setState({copiedUrl: false});
+      }
     },
 
     handleShareButtonClick: function(event) {
       event.preventDefault();
 
       var providers = this.props.socialShareProviders;
       // If there are no providers available currently, save a click by dispatching
       // the 'AddSocialShareProvider' right away.
       if (!providers || !providers.length) {
         this.props.dispatcher.dispatch(new sharedActions.AddSocialShareProvider());
         return;
       }
 
       this.toggleDropdownMenu();
     },
 
-    handleAddContextClick: function(event) {
-      event.preventDefault();
-
-      if (this.props.onAddContextClick) {
-        this.props.onAddContextClick();
-      }
-    },
-
     handleEditContextClose: function() {
       if (this.props.onEditContextClose) {
         this.props.onEditContextClose();
       }
     },
 
     render: function() {
       if (!this.props.show) {
         return null;
       }
 
-      var canAddContext = this.props.mozLoop.getLoopPref("contextInConversations.enabled") &&
-        // Don't show the link when we're showing the edit form already:
-        !this.props.showEditContext &&
-        // Don't show the link when there's already context data available:
-        !(this.props.roomData.roomContextUrls || this.props.roomData.roomDescription);
-
       var cx = React.addons.classSet;
       return (
         <div className="room-invitation-overlay">
           <div className="room-invitation-content">
             <p className={cx({hide: this.props.showEditContext})}>
-              {mozL10n.get("invite_header_text")}
+              {mozL10n.get("invite_header_text2")}
             </p>
-            <a className={cx({hide: !canAddContext, "room-invitation-addcontext": true})}
-               onClick={this.handleAddContextClick}>
-              {mozL10n.get("context_add_some_label")}
-            </a>
           </div>
           <div className={cx({
             "btn-group": true,
             "call-action-group": true,
             hide: this.props.showEditContext
           })}>
-            <button className="btn btn-info btn-email"
-                    onClick={this.handleEmailButtonClick}>
-              {mozL10n.get("email_link_button")}
-            </button>
-            <button className="btn btn-info btn-copy"
-                    onClick={this.handleCopyButtonClick}>
-              {this.state.copiedUrl ? mozL10n.get("copied_url_button") :
-                                      mozL10n.get("copy_url_button2")}
-            </button>
-            <button className="btn btn-info btn-share"
-                    onClick={this.handleShareButtonClick}
-                    ref="anchor">
-              {mozL10n.get("share_button3")}
-            </button>
+            <div className={cx({
+                "btn-copy": true,
+                "invite-button": true,
+                "triggered": this.state.copiedUrl
+              })}
+              onClick={this.handleCopyButtonClick}>
+              <img src="loop/shared/img/svg/glyph-link-16x16.svg" />
+              <p>{mozL10n.get("invite_copy_" +
+                (this.state.copiedUrl ? "triggered" : "button"))}</p>
+            </div>
+            <div className="btn-email invite-button"
+              onClick={this.handleEmailButtonClick}
+              onMouseOver={this.resetTriggeredButtons}>
+              <img src="loop/shared/img/svg/glyph-email-16x16.svg" />
+              <p>{mozL10n.get("invite_email_button")}</p>
+            </div>
           </div>
           <SocialShareDropdown
             dispatcher={this.props.dispatcher}
             ref="menu"
             roomUrl={this.props.roomData.roomUrl}
             show={this.state.showMenu}
             socialShareProviders={this.props.socialShareProviders} />
           <DesktopRoomEditContextView
--- a/browser/components/loop/content/shared/css/conversation.css
+++ b/browser/components/loop/content/shared/css/conversation.css
@@ -263,16 +263,51 @@ html[dir="rtl"] .conversation-toolbar-bt
   max-width: 100%;
 }
 
 .call-action-group .btn-group-chevron,
 .call-action-group .btn-group {
   width: 100%;
 }
 
+.call-action-group > .invite-button {
+  margin: 0 4px;
+  position: relative;
+}
+
+.call-action-group > .invite-button > img {
+  background-color: #00a9dc;
+  border-radius: 100%;
+  height: 28px;
+  width: 28px;
+}
+
+.call-action-group > .invite-button:hover > img {
+  background-color: #5cccee;
+}
+
+.call-action-group > .invite-button.triggered > img {
+  background-color: #56b397;
+}
+
+.call-action-group > .invite-button > p {
+  display: none;
+  /* Position the text under the button while centering it without impacting the
+   * rest of the layout */
+  left: -10rem;
+  margin: .5rem 0 0;
+  position: absolute;
+  right: -10rem;
+}
+
+.call-action-group > .invite-button.triggered > p,
+.call-action-group > .invite-button:hover > p {
+  display: block;
+}
+
 .direct-call-failure,
 .room-failure {
   /* This flex allows us to not calculate the height of the logo area
      versus the buttons */
   display: flex;
   flex-direction: column;
   align-items: center;
   justify-content: space-between;
@@ -658,63 +693,40 @@ html[dir="rtl"] .room-conversation-wrapp
   margin-top: 15px;
   width: 20px;
   height: 20px;
   background: transparent url("../img/svg/glyph-help-16x16.svg") no-repeat;
 }
 
 .room-invitation-overlay {
   position: absolute;
-  background: rgba(255, 255, 255, 0.6);
+  background: rgba(255, 255, 255, 0.85);
   top: 0;
   height: 100%;
   right: 0;
   left: 0;
   text-align: center;
-  color: #fff;
+  color: #000;
   z-index: 1010;
   display: flex;
   flex-flow: column nowrap;
   justify-content: flex-start;
   align-items: stretch;
 }
 
 .room-invitation-content {
   flex: 1 1 auto;
   display: flex;
   flex-flow: column nowrap;
   justify-content: center;
   align-items: center;
 }
 
 .room-invitation-overlay .btn-group {
-  padding: 0 0 5rem 0;
-}
-
-.room-invitation-addcontext {
-  color: #0095dd;
-  padding-left: 1.5em;
-  margin-bottom: 1em;
-  background-image: url("../img/icons-10x10.svg#edit-active");
-  background-size: 1em 1em;
-  background-repeat: no-repeat;
-  background-position: left top;
-  font-size: 1em;
-  cursor: pointer;
-}
-
-.room-invitation-addcontext:hover,
-.room-invitation-addcontext:hover:active {
-  text-decoration: underline;
-}
-
-html[dir="rtl"] .room-invitation-addcontext {
-  padding-left: 0;
-  padding-right: 1.5em;
-  background-position: right top;
+  padding: 0 0 10rem;
 }
 
 .share-service-dropdown {
   color: #000;
   text-align: start;
   bottom: auto;
   top: 0;
   overflow: hidden;
@@ -799,16 +811,17 @@ body[platform="win"] .share-service-drop
 }
 
 .room-context > .error-display-area.error {
   margin: 1em 0 .5em 0;
   text-align: center;
   text-shadow: 1px 1px 0 rgba(0,0,0,.3);
 }
 
+.room-invitation-content,
 .room-context-header {
   color: #333;
   font-size: 1.2rem;
   font-weight: bold;
   margin: 1rem auto;
 }
 
 .room-context > form {
new file mode 100644
--- /dev/null
+++ b/browser/components/loop/content/shared/img/svg/glyph-email-16x16.svg
@@ -0,0 +1,1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill="#FFF" d="M12 10.4c0 .2-.1.4-.2.5-.1.1-.3.2-.5.2H4.7c-.2 0-.4-.1-.5-.2-.1-.1-.2-.3-.2-.5V6.9c.1.1.3.3.5.4 1 .7 1.8 1.2 2.2 1.5.1.1.3.2.4.3.1.1.2.1.4.2s.3.1.5.1.3 0 .5-.1.3-.1.4-.2c.1-.1.3-.2.4-.3.5-.4 1.2-.9 2.2-1.5.2-.1.4-.3.5-.4v3.5zm-.2-4.2c-.1.2-.3.4-.5.5-1.1.8-1.8 1.3-2.1 1.5 0 0-.1.1-.2.1-.1.2-.2.2-.3.3-.1 0-.1.1-.2.1-.1.1-.2.1-.3.1h-.4c-.1 0-.2-.1-.3-.1-.1-.1-.2-.1-.2-.1-.1-.1-.2-.1-.3-.2-.1-.1-.1-.1-.1-.2-.3-.1-.7-.4-1.2-.8-.5-.3-.8-.5-.9-.6-.2-.1-.4-.3-.6-.5S4 5.9 4 5.7c0-.2.1-.4.2-.6.1-.2.3-.2.5-.2h6.6c.2 0 .4.1.5.2.1.1.2.3.2.5s-.1.4-.2.6z"/></svg>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/browser/components/loop/content/shared/img/svg/glyph-facebook-16x16.svg
@@ -0,0 +1,1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill="#FFF" d="M12 11.6c0 .1 0 .2-.1.3s-.2.1-.3.1h-2V8.9h1l.2-1.2H9.5v-.8c0-.2 0-.3.1-.4.1-.1.2-.1.5-.1h.6V5.3h-.9c-.4-.1-.8 0-1.1.3-.3.3-.4.7-.4 1.2v.9h-1v1.2h1V12H4.4c-.1 0-.2 0-.3-.1-.1-.1-.1-.2-.1-.3V4.4c0-.1 0-.2.1-.3.1-.1.2-.1.3-.1h7.1c.1 0 .2 0 .3.1.2.1.2.2.2.3v7.2z"/></svg>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/browser/components/loop/content/shared/img/svg/glyph-link-16x16.svg
@@ -0,0 +1,1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill="#FFF" d="M12 9.9c0 .4-.1.7-.4 1l-.7.7c-.3.3-.6.4-1 .4s-.7-.1-1-.4l-1-1c-.3-.3-.4-.6-.4-1s.1-.7.4-1l-.4-.5c-.3.3-.6.4-1 .4s-.7-.1-1-.4l-1-1c-.4-.3-.5-.6-.5-1s.1-.7.4-1l.7-.7c.3-.3.6-.4 1-.4s.7.1 1 .4l1 1c.3.3.4.6.4 1s-.1.7-.4 1l.4.4c.3-.3.6-.4 1-.4s.7.1 1 .4l1 1c.4.4.5.7.5 1.1zM7.6 6.4c0-.1 0-.2-.1-.3l-1-1c-.1-.1-.2-.2-.4-.2-.1 0-.2.1-.3.2l-.7.7c-.1.1-.2.2-.2.3 0 .1 0 .2.1.3l1 1c.1.1.2.1.3.1.1 0 .3-.1.4-.2l-.1-.1v.1s0-.1-.1-.1l-.1-.1V7c0-.1 0-.2.1-.3s.2-.1.3-.1h.1s.1 0 .1.1l.1.1.1.1.1.1c.3-.3.3-.4.3-.6zm3.5 3.5c0-.1 0-.2-.1-.3l-1-1c-.2-.2-.3-.2-.4-.2-.1 0-.3.1-.4.2l.1.1.1.1s0 .1.1.1l.1.1v.1c0 .1 0 .2-.1.3s-.3.2-.4.2H9s-.1 0-.1-.1l-.1-.1-.1-.1c-.1 0-.1-.1-.2-.1-.1.1-.1.2-.1.4 0 .1 0 .2.1.3l1 1c.1.1.2.1.3.1.1 0 .2 0 .3-.1l.7-.7c.2-.1.3-.2.3-.3z"/></svg>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/browser/components/loop/content/shared/img/svg/glyph-user-16x16.svg
@@ -0,0 +1,1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill="#FFF" d="M6.5 4.3c.4-.5.9-.7 1.5-.7s1.1.2 1.5.6.6.9.6 1.5-.2 1.1-.6 1.5c-.4.6-.9.8-1.5.8s-1.1-.2-1.5-.6c-.5-.5-.7-1-.7-1.6 0-.6.2-1.1.7-1.5zm5.1 7.7c-.3.3-.6.4-1.1.4h-5c-.5 0-.8-.1-1.1-.4-.3-.3-.4-.7-.4-1.1v-.6s0-.4.1-.6c0-.2.1-.4.2-.6.1-.2.1-.4.2-.6.1-.2.2-.3.4-.5.1-.1.2-.2.4-.2s.4-.2.7-.2c0 0 .1 0 .2.1s.3.2.4.3l.6.3s.5.1.8.1c.3 0 .5 0 .8-.1l.6-.3c.2-.1.3-.2.4-.3.1 0 .2-.1.2-.1.2 0 .4 0 .6.1.2.1.4.2.5.3.1.1.2.3.4.5s.2.4.2.6c.1.2.1.4.2.6 0 .2.1.4.1.6v.6c0 .4-.1.8-.4 1.1z"/></svg>
\ No newline at end of file
--- a/browser/components/loop/jar.mn
+++ b/browser/components/loop/jar.mn
@@ -50,17 +50,21 @@ browser.jar:
   content/browser/loop/shared/img/hangup-inverse-14x14.png      (content/shared/img/hangup-inverse-14x14.png)
   content/browser/loop/shared/img/hangup-inverse-14x14@2x.png   (content/shared/img/hangup-inverse-14x14@2x.png)
   content/browser/loop/shared/img/mute-inverse-14x14.png        (content/shared/img/mute-inverse-14x14.png)
   content/browser/loop/shared/img/mute-inverse-14x14@2x.png     (content/shared/img/mute-inverse-14x14@2x.png)
   content/browser/loop/shared/img/video-inverse-14x14.png       (content/shared/img/video-inverse-14x14.png)
   content/browser/loop/shared/img/video-inverse-14x14@2x.png    (content/shared/img/video-inverse-14x14@2x.png)
   content/browser/loop/shared/img/dropdown-inverse.png          (content/shared/img/dropdown-inverse.png)
   content/browser/loop/shared/img/dropdown-inverse@2x.png       (content/shared/img/dropdown-inverse@2x.png)
+  content/browser/loop/shared/img/svg/glyph-email-16x16.svg     (content/shared/img/svg/glyph-email-16x16.svg)
+  content/browser/loop/shared/img/svg/glyph-facebook-16x16.svg  (content/shared/img/svg/glyph-facebook-16x16.svg)
   content/browser/loop/shared/img/svg/glyph-help-16x16.svg      (content/shared/img/svg/glyph-help-16x16.svg)
+  content/browser/loop/shared/img/svg/glyph-link-16x16.svg      (content/shared/img/svg/glyph-link-16x16.svg)
+  content/browser/loop/shared/img/svg/glyph-user-16x16.svg      (content/shared/img/svg/glyph-user-16x16.svg)
   content/browser/loop/shared/img/svg/exit.svg                  (content/shared/img/svg/exit.svg)
   content/browser/loop/shared/img/svg/audio.svg                 (content/shared/img/svg/audio.svg)
   content/browser/loop/shared/img/svg/audio-hover.svg           (content/shared/img/svg/audio-hover.svg)
   content/browser/loop/shared/img/svg/audio-mute.svg            (content/shared/img/svg/audio-mute.svg)
   content/browser/loop/shared/img/svg/audio-mute-hover.svg      (content/shared/img/svg/audio-mute-hover.svg)
   content/browser/loop/shared/img/svg/video.svg                 (content/shared/img/svg/video.svg)
   content/browser/loop/shared/img/svg/video-hover.svg           (content/shared/img/svg/video-hover.svg)
   content/browser/loop/shared/img/svg/video-mute.svg            (content/shared/img/svg/video-mute.svg)
--- a/browser/components/loop/test/desktop-local/roomViews_test.js
+++ b/browser/components/loop/test/desktop-local/roomViews_test.js
@@ -9,17 +9,17 @@ describe("loop.roomViews", function () {
   var sharedActions = loop.shared.actions;
   var sharedUtils = loop.shared.utils;
   var sharedViews = loop.shared.views;
   var ROOM_STATES = loop.store.ROOM_STATES;
   var SCREEN_SHARE_STATES = loop.shared.utils.SCREEN_SHARE_STATES;
   var FAILURE_DETAILS = loop.shared.utils.FAILURE_DETAILS;
 
   var sandbox, dispatcher, roomStore, activeRoomStore, view;
-  var fakeWindow, fakeMozLoop, fakeContextURL;
+  var clock, fakeWindow, fakeMozLoop, fakeContextURL;
   var favicon = "data:image/x-icon;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
 
   beforeEach(function() {
     sandbox = sinon.sandbox.create();
 
     dispatcher = new loop.Dispatcher();
 
     fakeMozLoop = {
@@ -43,16 +43,18 @@ describe("loop.roomViews", function () {
           }
         }),
         update: sinon.stub().callsArgWith(2, null)
       },
       telemetryAddValue: sinon.stub(),
       setLoopPref: sandbox.stub()
     };
 
+    clock = sandbox.useFakeTimers();
+
     fakeWindow = {
       close: sinon.stub(),
       document: {},
       navigator: {
         mozLoop: fakeMozLoop
       },
       addEventListener: function() {},
       removeEventListener: function() {},
@@ -87,16 +89,17 @@ describe("loop.roomViews", function () {
       location: "http://invalid.com",
       thumbnail: "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="
     };
     sandbox.stub(dispatcher, "dispatch");
   });
 
   afterEach(function() {
     sandbox.restore();
+    clock.restore();
     loop.shared.mixins.setRootObject(window);
     view = null;
   });
 
   describe("ActiveRoomStoreMixin", function() {
     it("should merge initial state", function() {
       var TestView = React.createClass({
         mixins: [loop.roomViews.ActiveRoomStoreMixin],
@@ -245,92 +248,64 @@ describe("loop.roomViews", function () {
     describe("Copy Button", function() {
       beforeEach(function() {
         view = mountTestComponent({
           roomData: { roomUrl: "http://invalid" }
         });
       });
 
       it("should dispatch a CopyRoomUrl action when the copy button is pressed", function() {
-          var copyBtn = view.getDOMNode().querySelector(".btn-copy");
-
-          React.addons.TestUtils.Simulate.click(copyBtn);
+        var copyBtn = view.getDOMNode().querySelector(".btn-copy");
+        React.addons.TestUtils.Simulate.click(copyBtn);
 
-          sinon.assert.calledOnce(dispatcher.dispatch);
-          sinon.assert.calledWith(dispatcher.dispatch, new sharedActions.CopyRoomUrl({
-            roomUrl: "http://invalid",
-            from: "conversation"
-          }));
-        });
+        sinon.assert.calledOnce(dispatcher.dispatch);
+        sinon.assert.calledWith(dispatcher.dispatch, new sharedActions.CopyRoomUrl({
+          roomUrl: "http://invalid",
+          from: "conversation"
+        }));
+      });
 
       it("should change the text when the url has been copied", function() {
-          var copyBtn = view.getDOMNode().querySelector(".btn-copy");
-
-          React.addons.TestUtils.Simulate.click(copyBtn);
+        var copyBtn = view.getDOMNode().querySelector(".btn-copy");
+        React.addons.TestUtils.Simulate.click(copyBtn);
 
-          // copied_url_button is the l10n string.
-          expect(copyBtn.textContent).eql("copied_url_button");
+        // invite_copy_triggered is the l10n string.
+        expect(copyBtn.textContent).eql("invite_copy_triggered");
       });
-    });
 
-    describe("Share button", function() {
-      it("should dispatch a AddSocialShareProvider action when the share button is clicked", function() {
-        view = mountTestComponent();
-
-        var shareBtn = view.getDOMNode().querySelector(".btn-share");
+      it("should keep the text for a while after the url has been copied", function() {
+        var copyBtn = view.getDOMNode().querySelector(".btn-copy");
+        React.addons.TestUtils.Simulate.click(copyBtn);
+        clock.tick(loop.roomViews.DesktopRoomInvitationView.TRIGGERED_RESET_DELAY / 2);
 
-        React.addons.TestUtils.Simulate.click(shareBtn);
-
-        sinon.assert.calledOnce(dispatcher.dispatch);
-        sinon.assert.calledWith(dispatcher.dispatch,
-          new sharedActions.AddSocialShareProvider());
+        // invite_copy_triggered is the l10n string.
+        expect(copyBtn.textContent).eql("invite_copy_triggered");
       });
 
-      it("should toggle the share dropdown when the share button is clicked", function() {
-        view = mountTestComponent({
-          socialShareProviders: [{
-            name: "foo",
-            origin: "https://foo",
-            iconURL: "http://example.com/foo.png"
-          }]
-        });
+      it("should reset the text a bit after the url has been copied", function() {
+        var copyBtn = view.getDOMNode().querySelector(".btn-copy");
+        React.addons.TestUtils.Simulate.click(copyBtn);
+        clock.tick(loop.roomViews.DesktopRoomInvitationView.TRIGGERED_RESET_DELAY);
+
+        // invite_copy_button is the l10n string.
+        expect(copyBtn.textContent).eql("invite_copy_button");
+      });
 
-        var shareBtn = view.getDOMNode().querySelector(".btn-share");
+      it("should reset the text after the url has been copied then mouse over another button", function() {
+        var copyBtn = view.getDOMNode().querySelector(".btn-copy");
+        React.addons.TestUtils.Simulate.click(copyBtn);
+        var emailBtn = view.getDOMNode().querySelector(".btn-email");
+        React.addons.TestUtils.Simulate.mouseOver(emailBtn);
 
-        React.addons.TestUtils.Simulate.click(shareBtn);
-
-        expect(view.state.showMenu).to.eql(true);
-        expect(view.refs.menu.props.show).to.eql(true);
+        // invite_copy_button is the l10n string.
+        expect(copyBtn.textContent).eql("invite_copy_button");
       });
     });
 
     describe("Edit Context", function() {
-      it("should show the 'Add some context' link", function() {
-        view = mountTestComponent();
-
-        expect(view.getDOMNode().querySelector(
-          ".room-invitation-addcontext")).to.not.eql(null);
-      });
-
-      it("should call a callback when the link is clicked", function() {
-        var onAddContextClick = sinon.stub();
-        view = mountTestComponent({
-          onAddContextClick: onAddContextClick
-        });
-
-        var node = view.getDOMNode();
-        expect(node.querySelector(".room-context")).to.eql(null);
-
-        var addLink = node.querySelector(".room-invitation-addcontext");
-
-        React.addons.TestUtils.Simulate.click(addLink);
-
-        sinon.assert.calledOnce(onAddContextClick);
-      });
-
       it("should show the edit context view", function() {
         view = mountTestComponent({
           showEditContext: true
         });
 
         expect(view.getDOMNode().querySelector(".room-context")).to.not.eql(null);
       });
     });