diff --git a/browser/components/loop/content/css/contacts.css b/browser/components/loop/content/css/contacts.css
index e8c9acce7210..9d1aaccb649f 100644
--- a/browser/components/loop/content/css/contacts.css
+++ b/browser/components/loop/content/css/contacts.css
@@ -360,26 +360,20 @@ html[dir="rtl"] .contact > .dropdown-menu {
}
.contacts-gravatar-promo {
- position: relative;
- border: 1px dashed #c1c1c1;
+ border: 1px solid #5cccee;
border-radius: 2px;
- background-color: #fbfbfb;
- padding: 10px;
- margin-top: 10px;
+ background-color: #fff;
+ font-size: 1.2rem;
+ margin: 1.5rem;
+ padding: 1.5rem 1rem;
+ position: relative;
}
.contacts-gravatar-promo > p {
- margin-top: 2px;
- margin-bottom: 8px;
- margin-right: 4px;
+ margin-top: 0;
word-wrap: break-word;
}
-html[dir="rtl"] .contacts-gravatar-promo > p {
- margin-right: 0;
- margin-left: 4px;
-}
-
.contacts-gravatar-promo > p > a {
color: #0295df;
text-decoration: none;
@@ -400,6 +394,44 @@ html[dir="rtl"] .contacts-gravatar-promo > .button-close {
left: 8px;
}
+.contacts-gravatar-avatars {
+ height: 50px;
+ margin: 1.5rem auto;
+ text-align: center;
+ width: 200px;
+}
+
+.contacts-gravatar-avatars img {
+ margin: 0 1.5rem;
+ vertical-align: middle;
+ width: 50px;
+}
+
+/* Adjust the Firefox avatar because it has pointy ears. */
+.contacts-gravatar-avatars img:last-child {
+ transform: scale(1.08) translateY(-2px);
+}
+
+.contacts-gravatar-arrow {
+ border-color: #9b9b9b;
+ border-style: solid solid none none;
+ border-width: 2px;
+ display: inline-block;
+ height: 1.5rem;
+ -moz-margin-start: -.75rem;
+ transform: rotateZ(45deg);
+ vertical-align: middle;
+ width: 1.5rem;
+}
+
+html[dir="rtl"] .contacts-gravatar-arrow {
+ transform: rotateZ(225deg);
+}
+
+.contacts-gravatar-buttons {
+ padding: 0 .5rem;
+}
+
.contact-controls {
padding: 0 16px;
}
diff --git a/browser/components/loop/content/css/panel.css b/browser/components/loop/content/css/panel.css
index 83af3f584c4d..311881b920bb 100644
--- a/browser/components/loop/content/css/panel.css
+++ b/browser/components/loop/content/css/panel.css
@@ -265,6 +265,12 @@ html[dir="rtl"] .tab-view li:nth-child(2).selected ~ .slide-bar {
font-weight: lighter;
}
+/* Don't show the empty contacts image if we're showing gravatar promo. */
+.contacts-gravatar-promo ~ .contact-list-empty {
+ background-image: none;
+ padding-top: 3%;
+}
+
.contact-list-empty {
padding-top: 27%;
}
diff --git a/browser/components/loop/content/js/contacts.js b/browser/components/loop/content/js/contacts.js
index 6859cf88bdf3..f4bbe72d7da9 100644
--- a/browser/components/loop/content/js/contacts.js
+++ b/browser/components/loop/content/js/contacts.js
@@ -134,11 +134,17 @@ loop.contacts = (function(_, mozL10n) {
onClick: this.handleCloseButtonClick}),
React.createElement("p", {dangerouslySetInnerHTML: {__html: message},
onClick: this.handleLinkClick}),
- React.createElement(ButtonGroup, null,
- React.createElement(Button, {caption: mozL10n.get("gravatars_promo_button_nothanks"),
+ React.createElement("div", {className: "contacts-gravatar-avatars"},
+ React.createElement("img", {src: "loop/shared/img/avatars.svg#orange-avatar"}),
+ React.createElement("span", {className: "contacts-gravatar-arrow"}),
+ React.createElement("img", {src: "loop/shared/img/firefox-avatar.svg"})
+ ),
+ React.createElement(ButtonGroup, {additionalClass: "contacts-gravatar-buttons"},
+ React.createElement(Button, {additionalClass: "secondary",
+ caption: mozL10n.get("gravatars_promo_button_nothanks2"),
onClick: this.handleCloseButtonClick}),
- React.createElement(Button, {additionalClass: "button-accept",
- caption: mozL10n.get("gravatars_promo_button_use"),
+ React.createElement(Button, {additionalClass: "secondary",
+ caption: mozL10n.get("gravatars_promo_button_use2"),
onClick: this.handleUseButtonClick})
)
)
@@ -666,10 +672,10 @@ loop.contacts = (function(_, mozL10n) {
return (
React.createElement("div", {className: "contact-list-empty"},
React.createElement("p", {className: "panel-text-large"},
- mozL10n.get("no_contacts_message_heading")
+ mozL10n.get("no_contacts_message_heading2")
),
React.createElement("p", {className: "panel-text-medium"},
- mozL10n.get("no_contacts_import_or_add")
+ mozL10n.get("no_contacts_import_or_add2")
)
)
);
@@ -714,7 +720,7 @@ loop.contacts = (function(_, mozL10n) {
busy: this.state.importBusy})})
),
React.createElement(Button, {additionalClass: "primary",
- caption: mozL10n.get("new_contact_button"),
+ caption: mozL10n.get("new_contact_button2"),
onClick: this.handleAddContactButtonClick})
)
);
@@ -726,9 +732,7 @@ loop.contacts = (function(_, mozL10n) {
}
return (
- React.createElement("div", {className: "content-area"},
- React.createElement(GravatarPromo, {handleUse: this.handleUseGravatar})
- )
+ React.createElement(GravatarPromo, {handleUse: this.handleUseGravatar})
);
},
diff --git a/browser/components/loop/content/js/contacts.jsx b/browser/components/loop/content/js/contacts.jsx
index 3b258f70e381..ed94abe5cba1 100644
--- a/browser/components/loop/content/js/contacts.jsx
+++ b/browser/components/loop/content/js/contacts.jsx
@@ -134,11 +134,17 @@ loop.contacts = (function(_, mozL10n) {
onClick={this.handleCloseButtonClick} />
-
-
);
@@ -726,9 +732,7 @@ loop.contacts = (function(_, mozL10n) {
}
return (
-
-
-
+
);
},
diff --git a/browser/components/loop/content/shared/img/firefox-avatar.svg b/browser/components/loop/content/shared/img/firefox-avatar.svg
new file mode 100644
index 000000000000..d58278708fcf
--- /dev/null
+++ b/browser/components/loop/content/shared/img/firefox-avatar.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/browser/components/loop/jar.mn b/browser/components/loop/jar.mn
index 051f14aecc95..087479eeaefe 100644
--- a/browser/components/loop/jar.mn
+++ b/browser/components/loop/jar.mn
@@ -95,6 +95,7 @@ browser.jar:
content/browser/loop/shared/img/empty_conversations.svg (content/shared/img/empty_conversations.svg)
content/browser/loop/shared/img/empty_search.svg (content/shared/img/empty_search.svg)
content/browser/loop/shared/img/avatars.svg (content/shared/img/avatars.svg)
+ content/browser/loop/shared/img/firefox-avatar.svg (content/shared/img/firefox-avatar.svg)
# Shared scripts
content/browser/loop/shared/js/actions.js (content/shared/js/actions.js)
diff --git a/browser/components/loop/test/desktop-local/contacts_test.js b/browser/components/loop/test/desktop-local/contacts_test.js
index 036149865b0c..c25889a2d11f 100644
--- a/browser/components/loop/test/desktop-local/contacts_test.js
+++ b/browser/components/loop/test/desktop-local/contacts_test.js
@@ -203,6 +203,9 @@ describe("loop.contacts", function() {
var promo = listView.getDOMNode().querySelector(".contacts-gravatar-promo");
expect(promo).to.not.equal(null);
+ var avatars = listView.getDOMNode().querySelectorAll(".contacts-gravatar-avatars img");
+ expect(avatars).to.have.length(2, "two example avatars are shown");
+
checkGravatarContacts(false);
});
@@ -238,7 +241,7 @@ describe("loop.contacts", function() {
}));
React.addons.TestUtils.Simulate.click(listView.getDOMNode().querySelector(
- ".contacts-gravatar-promo .button-accept"));
+ ".contacts-gravatar-promo .secondary:last-child"));
sinon.assert.calledTwice(navigator.mozLoop.setLoopPref);
@@ -255,7 +258,7 @@ describe("loop.contacts", function() {
}));
React.addons.TestUtils.Simulate.click(listView.getDOMNode().querySelector(
- ".contacts-gravatar-promo .button-accept"));
+ ".contacts-gravatar-promo .secondary:last-child"));
sinon.assert.calledTwice(navigator.mozLoop.setLoopPref);
sinon.assert.calledWithExactly(navigator.mozLoop.setLoopPref, "contacts.gravatars.promo", false);
@@ -271,7 +274,7 @@ describe("loop.contacts", function() {
}));
React.addons.TestUtils.Simulate.click(listView.getDOMNode().querySelector(
- ".contacts-gravatar-promo .button-close"));
+ ".contacts-gravatar-promo .secondary:first-child"));
var promo = listView.getDOMNode().querySelector(".contacts-gravatar-promo");
expect(promo).to.equal(null);
@@ -285,6 +288,37 @@ describe("loop.contacts", function() {
startForm: function() {}
}));
+ React.addons.TestUtils.Simulate.click(listView.getDOMNode().querySelector(
+ ".contacts-gravatar-promo .secondary:first-child"));
+
+ sinon.assert.calledOnce(navigator.mozLoop.setLoopPref);
+ sinon.assert.calledWithExactly(navigator.mozLoop.setLoopPref,
+ "contacts.gravatars.promo", false);
+ });
+
+ it("should hide the gravatars promo box when the 'close' X button is clicked", function() {
+ listView = TestUtils.renderIntoDocument(
+ React.createElement(loop.contacts.ContactsList, {
+ mozLoop: navigator.mozLoop,
+ notifications: notifications,
+ startForm: function() {}
+ }));
+
+ React.addons.TestUtils.Simulate.click(listView.getDOMNode().querySelector(
+ ".contacts-gravatar-promo .button-close"));
+
+ var promo = listView.getDOMNode().querySelector(".contacts-gravatar-promo");
+ expect(promo).to.equal(null);
+ });
+
+ it("should set prefs correctly when the 'close' X button is clicked", function() {
+ listView = TestUtils.renderIntoDocument(
+ React.createElement(loop.contacts.ContactsList, {
+ mozLoop: navigator.mozLoop,
+ notifications: notifications,
+ startForm: function() {}
+ }));
+
React.addons.TestUtils.Simulate.click(listView.getDOMNode().querySelector(
".contacts-gravatar-promo .button-close"));
@@ -326,9 +360,9 @@ describe("loop.contacts", function() {
it("should display the no contacts strings", function() {
sinon.assert.calledWithExactly(mozL10nGetSpy,
- "no_contacts_message_heading");
+ "no_contacts_message_heading2");
sinon.assert.calledWithExactly(mozL10nGetSpy,
- "no_contacts_import_or_add");
+ "no_contacts_import_or_add2");
});
});
diff --git a/browser/locales/en-US/chrome/browser/loop/loop.properties b/browser/locales/en-US/chrome/browser/loop/loop.properties
index ec09b3b16ed6..2c42e54bc34e 100644
--- a/browser/locales/en-US/chrome/browser/loop/loop.properties
+++ b/browser/locales/en-US/chrome/browser/loop/loop.properties
@@ -88,9 +88,9 @@ settings_menu_button_tooltip=Settings
## the search field.
contacts_search_placesholder2=Search…
-## LOCALIZATION NOTE (new_contact_button): This is the button to open the
+## LOCALIZATION NOTE (new_contact_button2): This is the button to open the
## new contact sub-panel.
-new_contact_button=New Contact
+new_contact_button2=Add new contact
## LOCALIZATION NOTE (contact_form_*_placeholder):
## These are the placeholders for the inputs for entering or editing a contact
## Click the 'New Contact' button to see the fields.
@@ -131,12 +131,12 @@ import_contacts_success_message={{total}} contact was successfully imported.;{{t
## LOCALIZATION NOTE(sync_contacts_button): This button is displayed in place of
## importing_contacts_button once contacts have been imported once.
sync_contacts_button=Sync Contacts
-## LOCALIZATION NOTE(no_contacts_message_heading): Title shown when user has no
+## LOCALIZATION NOTE(no_contacts_message_heading2): Title shown when user has no
## contacts in his address book
-no_contacts_message_heading=No contacts yet
-## LOCALIZATION NOTE(no_contacts_import_or_add): Subheading inviting the user
+no_contacts_message_heading2=No contacts yet.
+## LOCALIZATION NOTE(no_contacts_import_or_add2): Subheading inviting the user
## to add people to his contact list
-no_contacts_import_or_add=Import or add someone
+no_contacts_import_or_add2=Add someone!
## LOCALIZATION NOTE(no_conversations_message_heading): Title shown when user
## has no conversations available.
no_conversations_message_heading=There are no conversations yet
@@ -208,8 +208,8 @@ video_call_menu_button=Video Conversation
gravatars_promo_message=You can automatically add profile icons to your contacts \
by sharing their email addresses with Gravatar. {{learn_more}}.
gravatars_promo_message_learnmore=Learn more
-gravatars_promo_button_nothanks=No Thanks
-gravatars_promo_button_use=Use Profile Icons
+gravatars_promo_button_nothanks2=No, thanks
+gravatars_promo_button_use2=Use profile icons
# Conversation Window Strings