Skip to content

Commit

Permalink
feat(pair): Create various UX for pair/unsupported
Browse files Browse the repository at this point in the history
Because:
* This page is confusing and not ideal for our users and we want to render various new UX to help them complete the pair flow

This commit:
* Adjusts 'Pair using an app' screen according to design, only show users this when the URL reflects a state that the user tried pairing with their system camera
* Adds a new 'Connecting your mobile device' state for when mobile users (not through system camera) reach this page, and conditionally renders an alert with 'Download Firefox now' link for iOS and Android if user is not on FF
* Previously, the 'default state' for this page was the system camera screen. This commit adds a new generic error state
* Tweaks pair/failure to match the new style/image, hides "Sign in with email" text if button is not shown
* Adds automatic Glean click events cad_redirect_mobile_download and cad_redirect_mobile_learn_more, adds custom events cad_redirect_mobile_view and cad_redirect_desktop_default_view

closes FXA-10136
  • Loading branch information
LZoog committed Sep 4, 2024
1 parent 0f699a3 commit 9de9d65
Show file tree
Hide file tree
Showing 12 changed files with 416 additions and 37 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
48 changes: 48 additions & 0 deletions packages/fxa-content-server/app/scripts/lib/glean/accountPref.js
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,54 @@ export const secondaryEmailSubmit = new EventMetricType(
[]
);

/**
* User viewed the backup codes page (step 2) of the 2FA setup funnel.
*
* Generated from `account_pref.two_step_auth_codes_view`.
*/
export const twoStepAuthCodesView = new EventMetricType(
{
category: 'account_pref',
name: 'two_step_auth_codes_view',
sendInPings: ['events'],
lifetime: 'ping',
disabled: false,
},
[]
);

/**
* User viewed form to enter one of their authentication codes (step 3).
*
* Generated from `account_pref.two_step_auth_enter_code_view`.
*/
export const twoStepAuthEnterCodeView = new EventMetricType(
{
category: 'account_pref',
name: 'two_step_auth_enter_code_view',
sendInPings: ['events'],
lifetime: 'ping',
disabled: false,
},
[]
);

/**
* Authentication code was successfully entered and submitted.
*
* Generated from `account_pref.two_step_auth_qr_code_success`.
*/
export const twoStepAuthQrCodeSuccess = new EventMetricType(
{
category: 'account_pref',
name: 'two_step_auth_qr_code_success',
sendInPings: ['events'],
lifetime: 'ping',
disabled: false,
},
[]
);

/**
* User started the 2FA setup process by viewing step 1 of the funnel, complete
* with QR code for scanning.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,23 @@

import EventMetricType from '@mozilla/glean/private/metrics/event';

/**
* User viewed the default page state on pair/unsupported after trying to access
* the pair flow
*
* Generated from `cad_redirect_desktop.default_view`.
*/
export const defaultView = new EventMetricType(
{
category: 'cad_redirect_desktop',
name: 'default_view',
sendInPings: ['events'],
lifetime: 'ping',
disabled: false,
},
[]
);

/**
* User clicked "Download Firefox" on the "Switch to Firefox" page after trying to
* access the pair flow
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// AUTOGENERATED BY glean_parser v14.5.2. DO NOT EDIT. DO NOT COMMIT.

import EventMetricType from '@mozilla/glean/private/metrics/event';

/**
* User viewed the "Connecting your mobile device" screen with instructions to
* open on desktop after trying to access the pair flow on mobile
*
* Generated from `cad_redirect_mobile.view`.
*/
export const view = new EventMetricType(
{
category: 'cad_redirect_mobile',
name: 'view',
sendInPings: ['events'],
lifetime: 'ping',
disabled: false,
},
[]
);
11 changes: 11 additions & 0 deletions packages/fxa-content-server/app/scripts/lib/glean/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import * as cachedLogin from './cachedLogin';
import * as cadApproveDevice from './cadApproveDevice';
import * as cadFirefox from './cadFirefox';
import * as cadMobilePair from './cadMobilePair';
import * as cadRedirectMobile from './cadRedirectMobile';
import * as cadMobilePairUseApp from './cadMobilePairUseApp';
import * as cad from './cad';
import * as cadRedirectDesktop from './cadRedirectDesktop';
Expand Down Expand Up @@ -288,6 +289,12 @@ const recordEventMetric = (eventName: string, properties: EventProperties) => {
case 'cad_submit':
cad.submit.record();
break;
case 'cad_redirect_mobile_view':
cadRedirectMobile.view.record();
break;
case 'cad_redirect_desktop_default_view':
cadRedirectDesktop.defaultView.record();
break;
case 'cad_redirect_desktop_view':
cadRedirectDesktop.view.record();
break;
Expand Down Expand Up @@ -463,9 +470,13 @@ export const GleanMetrics = {
submit: createEventFn('cad_approve_device_submit'),
},
cadRedirectDesktop: {
defaultView: createEventFn('cad_redirect_desktop_default_view'),
view: createEventFn('cad_redirect_desktop_view'),
download: createEventFn('cad_redirect_desktop_download'),
},
cadRedirectMobile: {
view: createEventFn('cad_redirect_mobile_view'),
},
setPasswordThirdPartyAuth: {
view: createEventFn('third_party_auth_set_password_view'),
engage: createEventFn('third_party_auth_set_password_engage'),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
<div class="card">
<header>
<h1 id="fxa-pair-failure-header" class="card-header">
{{#t}}Pairing not successful{{/t}}
</h1>
</header>

<div class="card-base">
<section>
<div class="error"></div>
<div class="success"></div>

<form novalidate>
<div class="bg-image-pair-fail"></div>

<p>{{#t}}The setup process was terminated. Please sign in with your email.{{/t}}</p>
<header>
<h1 id="fxa-pair-failure-header" class="card-header">
{{#t}}Device pairing failed{{/t}}
</h1>
</header>

<p class="mt-3">{{#t}}The setup couldn’t be completed.{{/t}}{{#showSigninLink}} {{#t}}Please sign in with your email.{{/t}}{{/showSigninLink}}</p>

{{#showSigninLink}}
<div class="button-row">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
<div class="card-base">
<header>
{{#isDesktopNonFirefox}}
{{#showCADHeader}}
<header>
<h1 class="mb-5 text-grey-400 text-base">{{#t}}Connect another device{{/t}}</h1>
{{/isDesktopNonFirefox}}
{{^isDesktopNonFirefox}}
<h1 id="pair-unsupported-header" class="card-header">{{#t}}Pair using an app{{/t}}</h1>
{{/isDesktopNonFirefox}}
</header>
</header>
{{/showCADHeader}}

<section>
<div class="error"></div>
Expand All @@ -25,11 +22,35 @@
</div>
{{/isDesktopNonFirefox}}

{{^isDesktopNonFirefox}}
<div class="bg-image-pair-fail"></div>
{{#isMobile}}
{{#isSystemCameraUrl}}
<div class="bg-image-pair-fail"></div>
<h2 id="pair-unsupported-header" class="card-header" tabindex="-1">{{#t}}Pair using an app{{/t}}</h1>
<p class="mt-4">{{#t}}Did you use the system camera? You must pair from within a Firefox app.{{/t}}</p>
{{/isSystemCameraUrl}}
{{^isSystemCameraUrl}}
{{^isFirefox}}
<div class="flex bg-orange-50 px-4 py-3 rounded-lg mb-8">
<div class="bg-icon-warning bg-contain bg-center bg-no-repeat w-10" aria-label="{{#t}}Attention:{{/t}}" role="img"></div>
<p class="ps-3 text-sm">{{#t}}Oops! It looks like you’re not using Firefox.{{/t}} <a href="{{{ escapedMobileDownloadLink }}}" target="_blank" class="link-blue" data-glean-id="cad_redirect_mobile_download">{{#t}}Download Firefox now{{/t}}</a></p>
</div>
{{/isFirefox}}

<p>{{#t}}Did you use the system camera? You must pair from within a Firefox app.{{/t}}</p>
{{/isDesktopNonFirefox}}
<div class="bg-image-triple-device-hearts" role="img" aria-label="{{#t}}Devices with hearts on their screens{{/t}}"></div>

<h1 class="card-header">{{#t}}Connecting your mobile device with your Mozilla account{{/t}}</h1>
<p class="mt-4 text-base">Open Firefox on your computer, visit <b class="whitespace-nowrap">firefox.com/pair</b>, and follow the on-screen instructions to connect your mobile device.</p>
<p class="mt-3"><a href="https://support.mozilla.org/kb/how-do-i-set-sync-my-computer" target="_blank" class="link-blue" data-glean-id="cad_redirect_mobile_learn_more">{{#t}}Learn more{{/t}}</a></p>
{{/isSystemCameraUrl}}
{{/isMobile}}
{{^isMobile}}
{{^isDesktopNonFirefox}}
<!-- Users should never see this since desktop Firefox /pair should not redirect to pair/unsupported
but fallback to generic message if so -->
<div class="bg-image-pair-fail"></div>
<h2 id="pair-unsupported-header" class="card-header" tabindex="-1">{{#t}}Oops! Something went wrong.{{/t}}</h2>
<p class="mt-3">{{#t}}Please close this tab and try again.{{/t}}</p>
{{/isDesktopNonFirefox}}
{{/isMobile}}
</section>
</div>
26 changes: 22 additions & 4 deletions packages/fxa-content-server/app/scripts/views/pair/unsupported.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import FormView from '../form';
import Template from '../../templates/pair/unsupported.mustache';
import GleanMetrics from '../../lib/glean';
import UserAgentMixin from '../../lib/user-agent-mixin';
import UrlMixin from 'lib/url-mixin';

class PairUnsupportedView extends FormView {
template = Template;
Expand All @@ -22,21 +23,38 @@ class PairUnsupportedView extends FormView {

setInitialContext(context) {
const uap = this.getUserAgent();
const isFirefox = uap.isFirefox();
const isMobile = uap.isAndroid() || uap.isIos();
// Assume the user is on non-Firefox desktop in this case.
const isDesktopNonFirefox =
!uap.isFirefox() && !uap.isAndroid() && !uap.isIos();
const isDesktopNonFirefox = !isFirefox && !isMobile;
const isSystemCameraUrl = this.getHashParams(['channel_id']).channel_id;

// Links taken from buttons in /settings
const escapedMobileDownloadLink = uap.isIos()
? 'https://app.adjust.com/2uo1qc?redirect=https%3A%2F%2Fitunes.apple.com%2Fus%2Fapp%2Ffirefox-private-safe-browser%2Fid989804926'
: 'https://app.adjust.com/2uo1qc?redirect=https%3A%2F%2Fplay.google.com%2Fstore%2Fapps%2Fdetails%3Fid%3Dorg.mozilla.firefox';

if (isDesktopNonFirefox) {
GleanMetrics.cadRedirectDesktop.view();
} else {
} else if (isSystemCameraUrl) {
GleanMetrics.cadMobilePairUseAppView.view();
} else if (isMobile) {
GleanMetrics.cadRedirectMobile.view();
} else {
GleanMetrics.cadRedirectDesktop.defaultView();
}

context.set({
isDesktopNonFirefox,
isFirefox,
isMobile,
isSystemCameraUrl,
escapedMobileDownloadLink,
showCADHeader: !(isMobile && !isSystemCameraUrl),
});
}
}

Cocktail.mixin(PairUnsupportedView, UserAgentMixin);
Cocktail.mixin(PairUnsupportedView, UserAgentMixin, UrlMixin);

export default PairUnsupportedView;
4 changes: 2 additions & 2 deletions packages/fxa-content-server/app/styles/tailwind/images.css
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,6 @@
}

.bg-image-pair-fail {
@apply mt-9 mb-5 bg-center bg-no-repeat bg-contain h-36;
background-image: inline('../images/graphic_hearts_broken.svg');
@apply mb-5 bg-center bg-no-repeat bg-contain h-40;
background-image: inline('../images/graphic_broken_connection.svg');
}
Loading

0 comments on commit 9de9d65

Please sign in to comment.