From b459d5b70bd636f3f16a0d0d1fb94e900af6b2e6 Mon Sep 17 00:00:00 2001 From: Mark Banner Date: Thu, 5 Feb 2015 19:35:12 +0000 Subject: [PATCH] Bug 1045495 - Loop's link clicker UI needs new UX for notification of non supported platform. r=mikedeboer --- .../loop/content/shared/css/common.css | 3 +- .../loop/content/shared/css/conversation.css | 18 ----------- .../loop/content/shared/js/utils.js | 26 ++++++++++++---- browser/components/loop/standalone/Makefile | 1 + .../loop/standalone/content/css/webapp.css | 25 ++++++++++++++++ .../content/js/standaloneAppStore.js | 8 +++-- .../loop/standalone/content/js/webapp.js | 30 ++++++++++++++----- .../loop/standalone/content/js/webapp.jsx | 30 ++++++++++++++----- .../content/l10n/en-US/loop.properties | 9 ++++-- browser/components/loop/standalone/server.js | 3 +- .../components/loop/test/shared/utils_test.js | 28 ++++++++++++----- .../standalone/standaloneAppStore_test.js | 17 ++++++++--- browser/components/loop/ui/ui-showcase.js | 2 +- browser/components/loop/ui/ui-showcase.jsx | 2 +- 14 files changed, 144 insertions(+), 58 deletions(-) diff --git a/browser/components/loop/content/shared/css/common.css b/browser/components/loop/content/shared/css/common.css index dfa37e166547..b712acc08523 100644 --- a/browser/components/loop/content/shared/css/common.css +++ b/browser/components/loop/content/shared/css/common.css @@ -393,7 +393,8 @@ p { .info-panel h4 { color: #aaa; text-align: center; - font-weight: 300; + font-weight: 500; + font-size: 1.2em; margin: 0; } diff --git a/browser/components/loop/content/shared/css/conversation.css b/browser/components/loop/content/shared/css/conversation.css index 50098bbf2988..60a0024c4f42 100644 --- a/browser/components/loop/content/shared/css/conversation.css +++ b/browser/components/loop/content/shared/css/conversation.css @@ -305,24 +305,6 @@ flex: 1; } -/* Expired call url page */ - -.expired-url-info { - width: 400px; - margin: 0 auto; -} - -.promote-firefox { - text-align: center; - font-size: 18px; - line-height: 24px; - margin: 2em 0; -} - -.promote-firefox h3 { - font-weight: 300; -} - /* * Dropdown menu hidden behind a chevron * diff --git a/browser/components/loop/content/shared/js/utils.js b/browser/components/loop/content/shared/js/utils.js index e779208d15f2..67e1cf880148 100644 --- a/browser/components/loop/content/shared/js/utils.js +++ b/browser/components/loop/content/shared/js/utils.js @@ -84,8 +84,6 @@ loop.shared.utils = (function(mozL10n) { return !!localStorage.getItem(prefName); } - var IOS_REGEX = /^(iPad|iPhone|iPod)/; - function isFirefox(platform) { return platform.indexOf("Firefox") !== -1; } @@ -99,8 +97,26 @@ loop.shared.utils = (function(mozL10n) { return !!window.MozActivity && /mobi/i.test(platform); } - function isIOS(platform) { - return IOS_REGEX.test(platform); + /** + * Helper to get the platform if it is unsupported. + * + * @param {String} platform The platform this is running on. + * @return null for supported platforms, a string for unsupported platforms. + */ + function getUnsupportedPlatform(platform) { + if (/^(iPad|iPhone|iPod)/.test(platform)) { + return "ios"; + } + + if (/Windows Phone/i.test(platform)) { + return "windows_phone"; + } + + if (/BlackBerry/i.test(platform)) { + return "blackberry"; + } + + return null; } /** @@ -151,7 +167,7 @@ loop.shared.utils = (function(mozL10n) { getBoolPreference: getBoolPreference, isFirefox: isFirefox, isFirefoxOS: isFirefoxOS, - isIOS: isIOS, + getUnsupportedPlatform: getUnsupportedPlatform, locationData: locationData }; })(document.mozL10n || navigator.mozL10n); diff --git a/browser/components/loop/standalone/Makefile b/browser/components/loop/standalone/Makefile index 87c177f34f1f..10535535f4cf 100644 --- a/browser/components/loop/standalone/Makefile +++ b/browser/components/loop/standalone/Makefile @@ -88,3 +88,4 @@ config: @echo "loop.config.roomsSupportUrl = 'https://support.mozilla.org/kb/group-conversations-firefox-hello-webrtc';" >> content/config.js @echo "loop.config.guestSupportUrl = 'https://support.mozilla.org/kb/respond-firefox-hello-invitation-guest-mode';" >> content/config.js @echo "loop.config.generalSupportUrl = 'https://support.mozilla.org/kb/respond-firefox-hello-invitation-guest-mode';" >> content/config.js + @echo "loop.config.unsupportedPlatformUrl = 'https://support.mozilla.org/en-US/kb/which-browsers-will-work-firefox-hello-video-chat';" >> content/config.js diff --git a/browser/components/loop/standalone/content/css/webapp.css b/browser/components/loop/standalone/content/css/webapp.css index 86e51cf9cd46..934fd7227f53 100644 --- a/browser/components/loop/standalone/content/css/webapp.css +++ b/browser/components/loop/standalone/content/css/webapp.css @@ -234,6 +234,31 @@ p.standalone-btn-label { flex: 1; } +/** + * Unsupported/expired views + */ + +.highlight-issue-box { + width: 400px; + margin: 0 auto; +} + +.promote-firefox { + text-align: center; + font-size: 18px; + line-height: 24px; + margin: 2em 0; +} + +.promote-firefox h3 { + font-weight: 300; +} + +.btn-unsupported-device { + width: 80%; + line-height: 24px; +} + /** * Feedback form overlay (standalone only) */ diff --git a/browser/components/loop/standalone/content/js/standaloneAppStore.js b/browser/components/loop/standalone/content/js/standaloneAppStore.js index 677355817fc5..11ea90e87291 100644 --- a/browser/components/loop/standalone/content/js/standaloneAppStore.js +++ b/browser/components/loop/standalone/content/js/standaloneAppStore.js @@ -109,7 +109,10 @@ loop.store.StandaloneAppStore = (function() { var token; // Check if we're on a supported device/platform. - if (sharedUtils.isIOS(navigator.platform)) { + var unsupportedPlatform = + sharedUtils.getUnsupportedPlatform(navigator.platform); + + if (unsupportedPlatform) { windowType = "unsupportedDevice"; } else if (!this._sdk.checkSystemRequirements()) { windowType = "unsupportedBrowser"; @@ -127,7 +130,8 @@ loop.store.StandaloneAppStore = (function() { this.setStoreState({ windowType: windowType, - isFirefox: sharedUtils.isFirefox(navigator.userAgent) + isFirefox: sharedUtils.isFirefox(navigator.userAgent), + unsupportedPlatform: unsupportedPlatform }); // If we've not got a window ID, don't dispatch the action, as we don't need diff --git a/browser/components/loop/standalone/content/js/webapp.js b/browser/components/loop/standalone/content/js/webapp.js index 479a02aefcda..3ccb31d814c4 100644 --- a/browser/components/loop/standalone/content/js/webapp.js +++ b/browser/components/loop/standalone/content/js/webapp.js @@ -45,7 +45,7 @@ loop.webapp = (function($, _, OT, mozL10n) { render: function() { return ( - React.createElement("div", {className: "expired-url-info"}, + React.createElement("div", {className: "highlight-issue-box"}, React.createElement("div", {className: "info-panel"}, React.createElement("div", {className: "firefox-logo"}), React.createElement("h1", null, mozL10n.get("incompatible_browser_heading")), @@ -61,12 +61,28 @@ loop.webapp = (function($, _, OT, mozL10n) { * Unsupported Device view. */ var UnsupportedDeviceView = React.createClass({displayName: "UnsupportedDeviceView", + propTypes: { + platform: React.PropTypes.string.isRequired + }, + render: function() { + var unsupportedDeviceParams = { + clientShortname: mozL10n.get("clientShortname2"), + platform: mozL10n.get("unsupported_platform_" + this.props.platform) + }; + var unsupportedLearnMoreText = mozL10n.get("unsupported_platform_learn_more_link", + {clientShortname: mozL10n.get("clientShortname2")}); + return ( - React.createElement("div", null, - React.createElement("h2", null, mozL10n.get("incompatible_device")), - React.createElement("p", null, mozL10n.get("sorry_device_unsupported", {clientShortname: mozL10n.get("clientShortname2")})), - React.createElement("p", null, mozL10n.get("use_firefox_windows_mac_linux", {brandShortname: mozL10n.get("brandShortname")})) + React.createElement("div", {className: "highlight-issue-box"}, + React.createElement("div", {className: "info-panel"}, + React.createElement("div", {className: "firefox-logo"}), + React.createElement("h1", null, mozL10n.get("unsupported_platform_heading")), + React.createElement("h4", null, mozL10n.get("unsupported_platform_message", unsupportedDeviceParams)) + ), + React.createElement("p", null, + React.createElement("a", {className: "btn btn-large btn-accept btn-unsupported-device", + href: loop.config.unsupportedPlatformUrl}, unsupportedLearnMoreText)) ) ); } @@ -110,7 +126,7 @@ loop.webapp = (function($, _, OT, mozL10n) { render: function() { return ( - React.createElement("div", {className: "expired-url-info"}, + React.createElement("div", {className: "highlight-issue-box"}, React.createElement("div", {className: "info-panel"}, React.createElement("div", {className: "firefox-logo"}), React.createElement("h1", null, mozL10n.get("call_url_unavailable_notification_heading")), @@ -965,7 +981,7 @@ loop.webapp = (function($, _, OT, mozL10n) { render: function() { switch (this.state.windowType) { case "unsupportedDevice": { - return React.createElement(UnsupportedDeviceView, null); + return React.createElement(UnsupportedDeviceView, {platform: this.state.unsupportedPlatform}); } case "unsupportedBrowser": { return React.createElement(UnsupportedBrowserView, {isFirefox: this.state.isFirefox}); diff --git a/browser/components/loop/standalone/content/js/webapp.jsx b/browser/components/loop/standalone/content/js/webapp.jsx index b4cc77599fd7..01eae7306324 100644 --- a/browser/components/loop/standalone/content/js/webapp.jsx +++ b/browser/components/loop/standalone/content/js/webapp.jsx @@ -45,7 +45,7 @@ loop.webapp = (function($, _, OT, mozL10n) { render: function() { return ( -
+

{mozL10n.get("incompatible_browser_heading")}

@@ -61,12 +61,28 @@ loop.webapp = (function($, _, OT, mozL10n) { * Unsupported Device view. */ var UnsupportedDeviceView = React.createClass({ + propTypes: { + platform: React.PropTypes.string.isRequired + }, + render: function() { + var unsupportedDeviceParams = { + clientShortname: mozL10n.get("clientShortname2"), + platform: mozL10n.get("unsupported_platform_" + this.props.platform) + }; + var unsupportedLearnMoreText = mozL10n.get("unsupported_platform_learn_more_link", + {clientShortname: mozL10n.get("clientShortname2")}); + return ( -
-

{mozL10n.get("incompatible_device")}

-

{mozL10n.get("sorry_device_unsupported", {clientShortname: mozL10n.get("clientShortname2")})}

-

{mozL10n.get("use_firefox_windows_mac_linux", {brandShortname: mozL10n.get("brandShortname")})}

+
+
+
+

{mozL10n.get("unsupported_platform_heading")}

+

{mozL10n.get("unsupported_platform_message", unsupportedDeviceParams)}

+
+

+ {unsupportedLearnMoreText}

); } @@ -110,7 +126,7 @@ loop.webapp = (function($, _, OT, mozL10n) { render: function() { return ( -
+

{mozL10n.get("call_url_unavailable_notification_heading")}

@@ -965,7 +981,7 @@ loop.webapp = (function($, _, OT, mozL10n) { render: function() { switch (this.state.windowType) { case "unsupportedDevice": { - return ; + return ; } case "unsupportedBrowser": { return ; diff --git a/browser/components/loop/standalone/content/l10n/en-US/loop.properties b/browser/components/loop/standalone/content/l10n/en-US/loop.properties index 8d9ea07b6767..58582d42df2b 100644 --- a/browser/components/loop/standalone/content/l10n/en-US/loop.properties +++ b/browser/components/loop/standalone/content/l10n/en-US/loop.properties @@ -27,9 +27,12 @@ incompatible_browser_heading=Oops! incompatible_browser_message=Firefox Hello only works in browsers that support WebRTC powered_by_webrtc=The audio and video components of {{clientShortname}} are powered by WebRTC. use_latest_firefox=Please try this link in a WebRTC-enabled browser, such as {{firefoxBrandNameLink}}. -incompatible_device=Incompatible device -sorry_device_unsupported=Sorry, {{clientShortname}} does not currently support your device. -use_firefox_windows_mac_linux=Please open this page using the latest {{brandShortname}} on Windows, Android, Mac or Linux. +unsupported_platform_heading=Sorry! +unsupported_platform_message={{platform}} does not currently support {{clientShortname}} +unsupported_platform_ios=iOS +unsupported_platform_windows_phone=Windows Phone +unsupported_platform_blackberry=Blackberry +unsupported_platform_learn_more_link=Learn more about why your platform doesn't support {{clientShortname}} connection_error_see_console_notification=Call failed; see console for details. call_url_unavailable_notification_heading=Oops! call_url_unavailable_notification_message2=Sorry, this URL is not available. It may be expired or entered incorrectly. diff --git a/browser/components/loop/standalone/server.js b/browser/components/loop/standalone/server.js index 830fed17c1a1..b40b87af5fd2 100644 --- a/browser/components/loop/standalone/server.js +++ b/browser/components/loop/standalone/server.js @@ -34,7 +34,8 @@ function getConfigFile(req, res) { "loop.config.fxosApp.manifestUrl = 'http://fake-market.herokuapp.com/apps/packagedApp/manifest.webapp';", "loop.config.roomsSupportUrl = 'https://support.mozilla.org/kb/group-conversations-firefox-hello-webrtc';", "loop.config.guestSupportUrl = 'https://support.mozilla.org/kb/respond-firefox-hello-invitation-guest-mode';", - "loop.config.generalSupportUrl = 'https://support.mozilla.org/kb/respond-firefox-hello-invitation-guest-mode';" + "loop.config.generalSupportUrl = 'https://support.mozilla.org/kb/respond-firefox-hello-invitation-guest-mode';", + "loop.config.unsupportedPlatformUrl = 'https://support.mozilla.org/en-US/kb/which-browsers-will-work-firefox-hello-video-chat'" ].join("\n")); } diff --git a/browser/components/loop/test/shared/utils_test.js b/browser/components/loop/test/shared/utils_test.js index 4669cd0fb634..0567150736d1 100644 --- a/browser/components/loop/test/shared/utils_test.js +++ b/browser/components/loop/test/shared/utils_test.js @@ -22,15 +22,27 @@ describe("loop.shared.utils", function() { sandbox.restore(); }); - it("should detect iOS", function() { - expect(sharedUtils.isIOS("iPad")).eql(true); - expect(sharedUtils.isIOS("iPod")).eql(true); - expect(sharedUtils.isIOS("iPhone")).eql(true); - expect(sharedUtils.isIOS("iPhone Simulator")).eql(true); - }); + describe("#getUnsupportedPlatform", function() { + it("should detect iOS", function() { + expect(sharedUtils.getUnsupportedPlatform("iPad")).eql('ios'); + expect(sharedUtils.getUnsupportedPlatform("iPod")).eql('ios'); + expect(sharedUtils.getUnsupportedPlatform("iPhone")).eql('ios'); + expect(sharedUtils.getUnsupportedPlatform("iPhone Simulator")).eql('ios'); + }); - it("shouldn't detect iOS with other platforms", function() { - expect(sharedUtils.isIOS("MacIntel")).eql(false); + it("should detect Windows Phone", function() { + expect(sharedUtils.getUnsupportedPlatform("Windows Phone")) + .eql('windows_phone'); + }); + + it("should detect BlackBerry", function() { + expect(sharedUtils.getUnsupportedPlatform("BlackBerry")) + .eql('blackberry'); + }); + + it("shouldn't detect other platforms", function() { + expect(sharedUtils.getUnsupportedPlatform("MacIntel")).eql(null); + }); }); describe("#isFirefox", function() { diff --git a/browser/components/loop/test/standalone/standaloneAppStore_test.js b/browser/components/loop/test/standalone/standaloneAppStore_test.js index c7acf973a5fc..3bc964080c8a 100644 --- a/browser/components/loop/test/standalone/standaloneAppStore_test.js +++ b/browser/components/loop/test/standalone/standaloneAppStore_test.js @@ -57,7 +57,7 @@ describe("loop.store.StandaloneAppStore", function () { windowPath: "" }; - sandbox.stub(loop.shared.utils, "isIOS").returns(false); + sandbox.stub(loop.shared.utils, "getUnsupportedPlatform").returns(); sandbox.stub(loop.shared.utils, "isFirefox").returns(true); fakeSdk = { @@ -94,9 +94,18 @@ describe("loop.store.StandaloneAppStore", function () { expect(store.getStoreState().isFirefox).eql(false); }); - it("should set windowType to `unsupportedDevice` for IOS", function() { - // The stub should return true for this test. - loop.shared.utils.isIOS.returns(true); + it("should store the platform for unsupported platforms", function() { + loop.shared.utils.getUnsupportedPlatform.returns("fake"); + + store.extractTokenInfo( + new sharedActions.ExtractTokenInfo(fakeGetWindowData)); + + expect(store.getStoreState().unsupportedPlatform).eql("fake"); + }); + + it("should set windowType to `unsupportedDevice` for ios", function() { + // The stub should return a platform for this test. + loop.shared.utils.getUnsupportedPlatform.returns("ios"); store.extractTokenInfo( new sharedActions.ExtractTokenInfo(fakeGetWindowData)); diff --git a/browser/components/loop/ui/ui-showcase.js b/browser/components/loop/ui/ui-showcase.js index 96e262f35a10..ddd01af0137c 100644 --- a/browser/components/loop/ui/ui-showcase.js +++ b/browser/components/loop/ui/ui-showcase.js @@ -555,7 +555,7 @@ React.createElement(Section, {name: "UnsupportedDeviceView"}, React.createElement(Example, {summary: "Standalone Unsupported Device"}, React.createElement("div", {className: "standalone"}, - React.createElement(UnsupportedDeviceView, null) + React.createElement(UnsupportedDeviceView, {platform: "ios"}) ) ) ), diff --git a/browser/components/loop/ui/ui-showcase.jsx b/browser/components/loop/ui/ui-showcase.jsx index f721b95e4c71..696d4e71c9bc 100644 --- a/browser/components/loop/ui/ui-showcase.jsx +++ b/browser/components/loop/ui/ui-showcase.jsx @@ -555,7 +555,7 @@
- +