Bug 1184924 - Implement the refreshed design for the invitation overlay [r=Standard8, a=lizzard]
authorEd Lee <edilee@mozilla.com>
Fri, 18 Sep 2015 10:45:47 -0700
changeset 296329 6424691f9e9a6d3cfe75f5700bbe8583239f0b25
parent 296328 a895735dc41409726214cf0408150ecdf88e5869
child 296330 faeb6b4444cc01d4885f28f65ca5dac276fe06f3
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersStandard8, lizzard
bugs1184924
milestone43.0a2
Bug 1184924 - Implement the refreshed design for the invitation overlay [r=Standard8, a=lizzard]
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
@@ -312,16 +312,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;
@@ -883,63 +918,40 @@ html[dir="rtl"] .room-conversation-wrapp
 }
 
 .fx-embedded .room-conversation .conversation-toolbar .btn-hangup {
   background-image: url("../img/icons-14x14.svg#exit-white");
 }
 
 .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;
@@ -1022,16 +1034,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
@@ -53,17 +53,21 @@ browser.jar:
   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-account-16x16.svg   (content/shared/img/svg/glyph-account-16x16.svg)
   content/browser/loop/shared/img/svg/glyph-signin-16x16.svg    (content/shared/img/svg/glyph-signin-16x16.svg)
   content/browser/loop/shared/img/svg/glyph-signout-16x16.svg   (content/shared/img/svg/glyph-signout-16x16.svg)
+  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);
       });
     });