Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(pair): Create various UX for pair/unsupported #17517

Merged
merged 1 commit into from
Sep 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

QA recently reopened https://mozilla-hub.atlassian.net/browse/FXA-10258 and I have been stratching my head on this. I think the best thing to do is to remove the button completely and tell the user to login with their email.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also be able to close the above ticket as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm was that a requested feature? If we shouldn't spend more time trying to fix it (I'm also not sure what's going on without investigating, I see the params are passed), I'm OK with removing it and revisiting when we do React work on that page.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Chatted in Slack and Vijay will remove this with the linked ticket in a quick follow up after this lands.


{{#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}}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This conditional was easier than juggling it here in the mustache file.

<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>
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,40 @@ 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 hashParams = this.getHashParams(['channel_id, channel_key']);
const isSystemCameraUrl =
hashParams.channel_id && hashParams.channel_key && isMobile;

// 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