Bug 1696547 - Refactor MultiStageAboutWelcome to support Proton onboarding r=Mardak,emcminn

Differential Revision: https://phabricator.services.mozilla.com/D107954
This commit is contained in:
Punam Dahiya 2021-03-25 20:28:39 +00:00
Родитель 8ed6d71b3b
Коммит 9624bcba17
11 изменённых файлов: 868 добавлений и 537 удалений

Просмотреть файл

@ -40,6 +40,8 @@ module.exports = {
files: [
"content-src/aboutwelcome/components/Zap.jsx",
"content-src/aboutwelcome/components/MultiStageAboutWelcome.jsx",
"content-src/aboutwelcome/components/MultiStageScreen.jsx",
"content-src/aboutwelcome/components/MultiStageProtonScreen.jsx",
"content-src/aboutwelcome/components/ReturnToAMO.jsx",
"content-src/asrouter/templates/OnboardingMessage/**",
"content-src/asrouter/templates/FirstRun/**",

Просмотреть файл

@ -101,7 +101,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2);
/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react_dom__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var _components_MultiStageAboutWelcome__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3);
/* harmony import */ var _components_ReturnToAMO__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(9);
/* harmony import */ var _components_ReturnToAMO__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(11);
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
/* This Source Code Form is subject to the terms of the Mozilla Public
@ -183,7 +183,8 @@ class AboutWelcome extends react__WEBPACK_IMPORTED_MODULE_0___default.a.PureComp
screens: props.screens,
metricsFlowUri: this.state.metricsFlowUri,
message_id: props.messageId,
utm_term: props.UTMTerm
utm_term: props.UTMTerm,
design: props.design
});
}
@ -260,14 +261,16 @@ module.exports = ReactDOM;
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MultiStageAboutWelcome", function() { return MultiStageAboutWelcome; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SecondaryCTA", function() { return SecondaryCTA; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "StepsIndicator", function() { return StepsIndicator; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "WelcomeScreen", function() { return WelcomeScreen; });
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _MSLocalized__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4);
/* harmony import */ var _Zap__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(5);
/* harmony import */ var _HelpText__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(6);
/* harmony import */ var _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(7);
/* harmony import */ var _asrouter_templates_FirstRun_addUtmParams__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(8);
/* harmony import */ var _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(5);
/* harmony import */ var _MultiStageScreen__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(6);
/* harmony import */ var _MultiStageProtonScreen__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(9);
/* harmony import */ var _asrouter_templates_FirstRun_addUtmParams__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(10);
/* 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/. */
@ -283,7 +286,7 @@ const MultiStageAboutWelcome = props => {
// Send impression ping when respective screen first renders
props.screens.forEach(screen => {
if (index === screen.order) {
_lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_4__["AboutWelcomeUtils"].sendImpressionTelemetry(`${props.message_id}_${screen.id}`);
_lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__["AboutWelcomeUtils"].sendImpressionTelemetry(`${props.message_id}_${screen.id}`);
}
}); // Remember that a new screen has loaded for browser navigation
@ -310,12 +313,12 @@ const MultiStageAboutWelcome = props => {
Object(react__WEBPACK_IMPORTED_MODULE_0__["useEffect"])(() => {
(async () => {
if (metricsFlowUri) {
setFlowParams(await _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_4__["AboutWelcomeUtils"].fetchFlowParams(metricsFlowUri));
setFlowParams(await _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__["AboutWelcomeUtils"].fetchFlowParams(metricsFlowUri));
}
})();
}, [metricsFlowUri]); // Transition to next screen, opening about:home on last screen button CTA
const handleTransition = index < props.screens.length - 1 ? () => setScreenIndex(prevState => prevState + 1) : () => _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_4__["AboutWelcomeUtils"].handleUserAction({
const handleTransition = index < props.screens.length - 1 ? () => setScreenIndex(prevState => prevState + 1) : () => _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__["AboutWelcomeUtils"].handleUserAction({
type: "OPEN_ABOUT_PAGE",
data: {
args: "home",
@ -351,7 +354,7 @@ const MultiStageAboutWelcome = props => {
const showImportable = useImportable && importable.length >= 5;
if (!importTelemetrySent.current) {
_lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_4__["AboutWelcomeUtils"].sendImpressionTelemetry(`${props.message_id}_SITES`, {
_lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__["AboutWelcomeUtils"].sendImpressionTelemetry(`${props.message_id}_SITES`, {
display: showImportable ? "importable" : "static",
importable: importable.length
});
@ -368,7 +371,7 @@ const MultiStageAboutWelcome = props => {
})();
}, [useImportable, region]);
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react__WEBPACK_IMPORTED_MODULE_0___default.a.Fragment, null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: `outer-wrapper onboardingContainer`
className: `outer-wrapper onboardingContainer ${props.design}`
}, props.screens.map(screen => {
return index === screen.order ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(WelcomeScreen, {
key: screen.id,
@ -383,10 +386,38 @@ const MultiStageAboutWelcome = props => {
flowParams: flowParams,
activeTheme: activeTheme,
initialTheme: initialTheme,
setActiveTheme: setActiveTheme
setActiveTheme: setActiveTheme,
design: props.design
}) : null;
})));
};
const SecondaryCTA = props => {
let targetElement = props.position ? `secondary_button_${props.position}` : `secondary_button`;
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: props.position ? `secondary-cta ${props.position}` : "secondary-cta"
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__["Localized"], {
text: props.content[targetElement].text
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("span", null)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__["Localized"], {
text: props.content[targetElement].label
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("button", {
className: "secondary",
value: targetElement,
onClick: props.handleAction
})));
};
const StepsIndicator = props => {
let steps = [];
for (let i = 0; i < props.totalNumberOfScreens; i++) {
let className = i === props.order ? "current" : "";
steps.push( /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
key: i,
className: `indicator ${className}`
}));
}
return steps;
};
class WelcomeScreen extends react__WEBPACK_IMPORTED_MODULE_0___default.a.PureComponent {
constructor(props) {
super(props);
@ -431,7 +462,7 @@ class WelcomeScreen extends react__WEBPACK_IMPORTED_MODULE_0___default.a.PureCom
};
}
_lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_4__["AboutWelcomeUtils"].handleUserAction({
_lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__["AboutWelcomeUtils"].handleUserAction({
type,
data
});
@ -448,7 +479,7 @@ class WelcomeScreen extends react__WEBPACK_IMPORTED_MODULE_0___default.a.PureCom
} // Send telemetry before waiting on actions
_lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_4__["AboutWelcomeUtils"].sendActionTelemetry(props.messageId, event.currentTarget.value);
_lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__["AboutWelcomeUtils"].sendActionTelemetry(props.messageId, event.currentTarget.value);
let {
action
} = targetContent;
@ -456,11 +487,11 @@ class WelcomeScreen extends react__WEBPACK_IMPORTED_MODULE_0___default.a.PureCom
if (["OPEN_URL", "SHOW_FIREFOX_ACCOUNTS"].includes(action.type)) {
this.handleOpenURL(action, props.flowParams, props.UTMTerm);
} else if (action.type) {
_lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_4__["AboutWelcomeUtils"].handleUserAction(action); // Wait until migration closes to complete the action
_lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__["AboutWelcomeUtils"].handleUserAction(action); // Wait until migration closes to complete the action
if (action.type === "SHOW_MIGRATION_WIZARD") {
await window.AWWaitForMigrationClose();
_lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_4__["AboutWelcomeUtils"].sendActionTelemetry(props.messageId, "migrate_close");
_lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__["AboutWelcomeUtils"].sendActionTelemetry(props.messageId, "migrate_close");
}
} // Wait until we become default browser to continue rest of action.
@ -478,7 +509,7 @@ class WelcomeScreen extends react__WEBPACK_IMPORTED_MODULE_0___default.a.PureCom
setTimeout(checkDefault, 100);
}
}());
_lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_4__["AboutWelcomeUtils"].sendActionTelemetry(props.messageId, "default_browser");
_lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__["AboutWelcomeUtils"].sendActionTelemetry(props.messageId, "default_browser");
} // A special tiles.action.theme value indicates we should use the event's value vs provided value.
@ -493,171 +524,37 @@ class WelcomeScreen extends react__WEBPACK_IMPORTED_MODULE_0___default.a.PureCom
}
}
renderSecondaryCTA(position) {
let targetElement = position ? `secondary_button_${position}` : `secondary_button`;
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: position ? `secondary-cta ${position}` : "secondary-cta"
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__["Localized"], {
text: this.props.content[targetElement].text
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("span", null)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__["Localized"], {
text: this.props.content[targetElement].label
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("button", {
className: "secondary",
value: targetElement,
onClick: this.handleAction
})));
}
renderTiles() {
switch (this.props.content.tiles.type) {
case "topsites":
return this.props.topSites && this.props.topSites.data ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: `tiles-container ${this.props.content.tiles.info ? "info" : ""}`
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: "tiles-topsites-section",
name: "topsites-section",
id: "topsites-section",
"aria-labelledby": "helptext",
role: "region"
}, this.props.topSites.data.slice(0, 5).map(({
icon,
label,
title
}) => /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: "site",
key: icon + label,
"aria-label": title ? title : label,
role: "img"
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: "icon",
style: icon ? {
backgroundColor: "transparent",
backgroundImage: `url(${icon})`
} : {}
}, icon ? "" : label && label[0].toUpperCase()), this.props.content.tiles.showTitles && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: "host"
}, title || label))))) : null;
case "theme":
return this.props.content.tiles.data ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: "tiles-theme-container"
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("fieldset", {
className: "tiles-theme-section"
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__["Localized"], {
text: this.props.content.subtitle
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("legend", {
className: "sr-only"
})), this.props.content.tiles.data.map(({
theme,
label,
tooltip,
description
}) => /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__["Localized"], {
key: theme + label,
text: typeof tooltip === "object" ? tooltip : {}
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("label", {
className: `theme${theme === this.props.activeTheme ? " selected" : ""}`,
title: theme + label
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__["Localized"], {
text: typeof description === "object" ? description : {}
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("input", {
type: "radio",
value: theme,
name: "theme",
checked: theme === this.props.activeTheme,
className: "sr-only input",
onClick: this.handleAction,
"data-l10n-attrs": "aria-description"
})), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: `icon ${theme}`
}), label && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__["Localized"], {
text: label
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: "text"
})))))))) : null;
case "video":
return this.props.content.tiles.source ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: `tiles-media-section ${this.props.content.tiles.media_type}`
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: "fade"
}), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("video", {
className: "media",
autoPlay: "true",
loop: "true",
muted: "true",
src: _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_4__["AboutWelcomeUtils"].hasDarkMode() ? this.props.content.tiles.source.dark : this.props.content.tiles.source.default
})) : null;
case "image":
return this.props.content.tiles.source ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: `${this.props.content.tiles.media_type}`
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("img", {
src: _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_4__["AboutWelcomeUtils"].hasDarkMode() && this.props.content.tiles.source.dark ? this.props.content.tiles.source.dark : this.props.content.tiles.source.default,
role: "presentation",
alt: ""
})) : null;
}
return null;
}
renderStepsIndicator() {
let steps = [];
for (let i = 0; i < this.props.totalNumberOfScreens; i++) {
let className = i === this.props.order ? "current" : "";
steps.push( /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
key: i,
className: `indicator ${className}`
}));
}
return steps;
}
renderHelpText() {
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_HelpText__WEBPACK_IMPORTED_MODULE_3__["HelpText"], {
text: this.props.content.help_text.text,
position: this.props.content.help_text.position,
hasImg: this.props.content.help_text.img
});
}
render() {
// Use the provided content or switch to an alternate one.
const {
content,
topSites
} = this.props;
let newContent = content;
if (content[this.state.alternateContent]) {
Object.assign(content, content[this.state.alternateContent]);
newContent = { ...content,
...content[this.state.alternateContent]
};
}
const showImportableSitesDisclaimer = content.tiles && content.tiles.type === "topsites" && topSites && topSites.showImportable;
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("main", {
className: `screen ${this.props.id}`
}, content.secondary_button_top ? this.renderSecondaryCTA("top") : null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: `brand-logo ${content.secondary_button_top ? "cta-top" : ""}`
}), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: "welcome-text"
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_Zap__WEBPACK_IMPORTED_MODULE_2__["Zap"], {
hasZap: content.zap,
text: content.title
}), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__["Localized"], {
text: content.subtitle
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("h2", null))), content.tiles ? this.renderTiles() : null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__["Localized"], {
text: content.primary_button ? content.primary_button.label : null
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("button", {
className: "primary",
value: "primary_button",
onClick: this.handleAction
}))), content.help_text && content.help_text.position === "default" ? this.renderHelpText() : null, content.secondary_button ? this.renderSecondaryCTA() : null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("nav", {
className: content.help_text && content.help_text.position === "footer" || showImportableSitesDisclaimer ? "steps has-helptext" : "steps",
"data-l10n-id": "onboarding-welcome-steps-indicator",
"data-l10n-args": `{"current": ${parseInt(this.props.order, 10) + 1}, "total": ${this.props.totalNumberOfScreens}}`
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("br", null), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("p", null), this.renderStepsIndicator()), content.help_text && content.help_text.position === "footer" || showImportableSitesDisclaimer ? this.renderHelpText() : null);
if (this.props.design === "proton") {
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MultiStageProtonScreen__WEBPACK_IMPORTED_MODULE_4__["MultiStageProtonScreen"], {
content: newContent,
id: this.props.id,
handleAction: this.handleAction
});
}
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MultiStageScreen__WEBPACK_IMPORTED_MODULE_3__["MultiStageScreen"], {
content: newContent,
id: this.props.id,
order: this.props.order,
topSites: topSites,
activeTheme: this.props.activeTheme,
totalNumberOfScreens: this.props.totalNumberOfScreens,
handleAction: this.handleAction
});
}
}
@ -729,132 +626,6 @@ const Localized = ({
/* 5 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Zap", function() { return Zap; });
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _MSLocalized__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4);
/* 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/. */
const MS_STRING_PROP = "string_id";
const ZAP_SIZE_THRESHOLD = 160;
function calculateZapLength() {
let span = document.querySelector(".zap");
if (!span) {
return;
}
let rect = span.getBoundingClientRect();
if (rect && rect.width > ZAP_SIZE_THRESHOLD) {
span.classList.add("long");
} else {
span.classList.add("short");
}
}
const Zap = props => {
Object(react__WEBPACK_IMPORTED_MODULE_0__["useEffect"])(() => {
requestAnimationFrame(() => calculateZapLength());
});
if (!props.text) {
return null;
}
if (props.hasZap) {
if (typeof props.text === "object" && props.text[MS_STRING_PROP]) {
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__["Localized"], {
text: props.text
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("h1", {
className: "welcomeZap"
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("span", {
"data-l10n-name": "zap",
className: "zap"
})));
} else if (typeof props.text === "string") {
// Parse string to zap style last word of the props.text
let titleArray = props.text.split(" ");
let lastWord = `${titleArray.pop()}`;
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("h1", {
className: "welcomeZap"
}, titleArray.join(" ").concat(" "), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("span", {
className: "zap"
}, lastWord));
}
} else {
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__["Localized"], {
text: props.text
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("h1", null));
}
return null;
};
/***/ }),
/* 6 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HelpText", function() { return HelpText; });
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _MSLocalized__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4);
/* 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/. */
const MS_STRING_PROP = "string_id";
const HelpText = props => {
if (!props.text) {
return null;
}
if (props.hasImg) {
if (typeof props.text === "object" && props.text[MS_STRING_PROP]) {
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__["Localized"], {
text: props.text
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("p", {
className: `helptext ${props.position}`
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("img", {
"data-l10n-name": "help-img",
className: `helptext-img ${props.position}`,
src: props.hasImg.src,
alt: ""
})));
} else if (typeof props.text === "string") {
// Add the img at the end of the props.text
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("p", {
className: `helptext ${props.position}`
}, props.text, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("img", {
className: `helptext-img ${props.position} end`,
src: props.hasImg.src,
alt: ""
}));
}
} else {
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__["Localized"], {
text: props.text
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("p", {
className: `helptext ${props.position}`
}));
}
return null;
};
/***/ }),
/* 7 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AboutWelcomeUtils", function() { return AboutWelcomeUtils; });
@ -964,10 +735,343 @@ const DEFAULT_RTAMO_CONTENT = {
}
};
/***/ }),
/* 6 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MultiStageScreen", function() { return MultiStageScreen; });
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5);
/* harmony import */ var _MSLocalized__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4);
/* harmony import */ var _Zap__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(7);
/* harmony import */ var _HelpText__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(8);
/* harmony import */ var _MultiStageAboutWelcome__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(3);
/* 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/. */
class MultiStageScreen extends react__WEBPACK_IMPORTED_MODULE_0___default.a.PureComponent {
renderTiles() {
switch (this.props.content.tiles.type) {
case "topsites":
return this.props.topSites && this.props.topSites.data ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: `tiles-container ${this.props.content.tiles.info ? "info" : ""}`
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: "tiles-topsites-section",
name: "topsites-section",
id: "topsites-section",
"aria-labelledby": "helptext",
role: "region"
}, this.props.topSites.data.slice(0, 5).map(({
icon,
label,
title
}) => /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: "site",
key: icon + label,
"aria-label": title ? title : label,
role: "img"
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: "icon",
style: icon ? {
backgroundColor: "transparent",
backgroundImage: `url(${icon})`
} : {}
}, icon ? "" : label && label[0].toUpperCase()), this.props.content.tiles.showTitles && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: "host"
}, title || label))))) : null;
case "theme":
return this.props.content.tiles.data ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: "tiles-theme-container"
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("fieldset", {
className: "tiles-theme-section"
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_2__["Localized"], {
text: this.props.content.subtitle
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("legend", {
className: "sr-only"
})), this.props.content.tiles.data.map(({
theme,
label,
tooltip,
description
}) => /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_2__["Localized"], {
key: theme + label,
text: typeof tooltip === "object" ? tooltip : {}
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("label", {
className: `theme${theme === this.props.activeTheme ? " selected" : ""}`,
title: theme + label
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_2__["Localized"], {
text: typeof description === "object" ? description : {}
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("input", {
type: "radio",
value: theme,
name: "theme",
checked: theme === this.props.activeTheme,
className: "sr-only input",
onClick: this.props.handleAction,
"data-l10n-attrs": "aria-description"
})), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: `icon ${theme}`
}), label && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_2__["Localized"], {
text: label
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: "text"
})))))))) : null;
case "video":
return this.props.content.tiles.source ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: `tiles-media-section ${this.props.content.tiles.media_type}`
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: "fade"
}), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("video", {
className: "media",
autoPlay: "true",
loop: "true",
muted: "true",
src: _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__["AboutWelcomeUtils"].hasDarkMode() ? this.props.content.tiles.source.dark : this.props.content.tiles.source.default
})) : null;
case "image":
return this.props.content.tiles.source ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: `${this.props.content.tiles.media_type}`
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("img", {
src: _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__["AboutWelcomeUtils"].hasDarkMode() && this.props.content.tiles.source.dark ? this.props.content.tiles.source.dark : this.props.content.tiles.source.default,
role: "presentation",
alt: ""
})) : null;
}
return null;
}
render() {
const {
content,
topSites
} = this.props;
const showImportableSitesDisclaimer = content.tiles && content.tiles.type === "topsites" && topSites && topSites.showImportable;
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("main", {
className: `screen ${this.props.id}`
}, content.secondary_button_top ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MultiStageAboutWelcome__WEBPACK_IMPORTED_MODULE_5__["SecondaryCTA"], {
content: content,
handleAction: this.props.handleAction,
position: "top"
}) : null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: `brand-logo ${content.secondary_button_top ? "cta-top" : ""}`
}), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: "welcome-text"
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_Zap__WEBPACK_IMPORTED_MODULE_3__["Zap"], {
hasZap: content.zap,
text: content.title
}), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_2__["Localized"], {
text: content.subtitle
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("h2", null))), content.tiles ? this.renderTiles() : null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_2__["Localized"], {
text: content.primary_button ? content.primary_button.label : null
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("button", {
className: "primary",
value: "primary_button",
onClick: this.props.handleAction
}))), content.help_text && content.help_text.position === "default" ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_HelpText__WEBPACK_IMPORTED_MODULE_4__["HelpText"], {
text: content.help_text.text,
position: content.help_text.position,
hasImg: content.help_text.img
}) : null, content.secondary_button ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MultiStageAboutWelcome__WEBPACK_IMPORTED_MODULE_5__["SecondaryCTA"], {
content: content,
handleAction: this.props.handleAction
}) : null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("nav", {
className: content.help_text && content.help_text.position === "footer" || showImportableSitesDisclaimer ? "steps has-helptext" : "steps",
"data-l10n-id": "onboarding-welcome-steps-indicator",
"data-l10n-args": `{"current": ${parseInt(this.props.order, 10) + 1}, "total": ${this.props.totalNumberOfScreens}}`
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("br", null), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("p", null), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MultiStageAboutWelcome__WEBPACK_IMPORTED_MODULE_5__["StepsIndicator"], {
order: this.props.order,
totalNumberOfScreens: this.props.totalNumberOfScreens
})), content.help_text && content.help_text.position === "footer" || showImportableSitesDisclaimer ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_HelpText__WEBPACK_IMPORTED_MODULE_4__["HelpText"], {
text: content.help_text.text,
position: content.help_text.position,
hasImg: content.help_text.img
}) : null);
}
}
/***/ }),
/* 7 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Zap", function() { return Zap; });
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _MSLocalized__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4);
/* 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/. */
const MS_STRING_PROP = "string_id";
const ZAP_SIZE_THRESHOLD = 160;
function calculateZapLength() {
let span = document.querySelector(".zap");
if (!span) {
return;
}
let rect = span.getBoundingClientRect();
if (rect && rect.width > ZAP_SIZE_THRESHOLD) {
span.classList.add("long");
} else {
span.classList.add("short");
}
}
const Zap = props => {
Object(react__WEBPACK_IMPORTED_MODULE_0__["useEffect"])(() => {
requestAnimationFrame(() => calculateZapLength());
});
if (!props.text) {
return null;
}
if (props.hasZap) {
if (typeof props.text === "object" && props.text[MS_STRING_PROP]) {
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__["Localized"], {
text: props.text
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("h1", {
className: "welcomeZap"
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("span", {
"data-l10n-name": "zap",
className: "zap"
})));
} else if (typeof props.text === "string") {
// Parse string to zap style last word of the props.text
let titleArray = props.text.split(" ");
let lastWord = `${titleArray.pop()}`;
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("h1", {
className: "welcomeZap"
}, titleArray.join(" ").concat(" "), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("span", {
className: "zap"
}, lastWord));
}
} else {
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__["Localized"], {
text: props.text
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("h1", null));
}
return null;
};
/***/ }),
/* 8 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HelpText", function() { return HelpText; });
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _MSLocalized__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4);
/* 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/. */
const MS_STRING_PROP = "string_id";
const HelpText = props => {
if (!props.text) {
return null;
}
if (props.hasImg) {
if (typeof props.text === "object" && props.text[MS_STRING_PROP]) {
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__["Localized"], {
text: props.text
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("p", {
className: `helptext ${props.position}`
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("img", {
"data-l10n-name": "help-img",
className: `helptext-img ${props.position}`,
src: props.hasImg.src,
alt: ""
})));
} else if (typeof props.text === "string") {
// Add the img at the end of the props.text
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("p", {
className: `helptext ${props.position}`
}, props.text, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("img", {
className: `helptext-img ${props.position} end`,
src: props.hasImg.src,
alt: ""
}));
}
} else {
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__["Localized"], {
text: props.text
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("p", {
className: `helptext ${props.position}`
}));
}
return null;
};
/***/ }),
/* 9 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MultiStageProtonScreen", function() { return MultiStageProtonScreen; });
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _MSLocalized__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4);
/* 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/. */
class MultiStageProtonScreen extends react__WEBPACK_IMPORTED_MODULE_0___default.a.PureComponent {
render() {
const {
content
} = this.props;
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("main", {
className: `screen ${this.props.id}`
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: "welcome-text"
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__["Localized"], {
text: content.title
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("h1", null)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__["Localized"], {
text: content.subtitle
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("h2", null))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__["Localized"], {
text: content.primary_button ? content.primary_button.label : null
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("button", {
className: "primary",
value: "primary_button",
onClick: this.props.handleAction
}))));
}
}
/***/ }),
/* 10 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BASE_PARAMS", function() { return BASE_PARAMS; });
@ -1006,7 +1110,7 @@ function addUtmParams(url, utmTerm) {
}
/***/ }),
/* 9 */
/* 11 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@ -1014,7 +1118,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ReturnToAMO", function() { return ReturnToAMO; });
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7);
/* harmony import */ var _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5);
/* harmony import */ var _MSLocalized__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4);
/* 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,

Просмотреть файл

@ -358,3 +358,9 @@ body {
opacity: 0.25; }
.onboardingContainer .steps .indicator.current {
opacity: 1; }
.onboardingContainer.proton {
background-image: url("chrome://branding/content/about-logo.svg");
background-repeat: no-repeat;
background-size: 25em; }
.onboardingContainer.proton .welcome-text {
margin-top: 10vw; }

Просмотреть файл

@ -74,6 +74,7 @@ class AboutWelcome extends React.PureComponent {
metricsFlowUri={this.state.metricsFlowUri}
message_id={props.messageId}
utm_term={props.UTMTerm}
design={props.design}
/>
);
}

Просмотреть файл

@ -109,8 +109,6 @@ body {
background-image: url('chrome://activity-stream/content/data/content/assets/long-zap.svg');
}
}
}
.welcome-text {
@ -510,4 +508,15 @@ body {
}
}
}
// TBD: Styles specific to Proton multistage welcome UI
&.proton {
background-image: url('chrome://branding/content/about-logo.svg');
background-repeat: no-repeat;
background-size: 25em;
.welcome-text {
margin-top: 10vw;
}
}
}

Просмотреть файл

@ -4,9 +4,9 @@
import React, { useState, useEffect, useRef } from "react";
import { Localized } from "./MSLocalized";
import { Zap } from "./Zap";
import { HelpText } from "./HelpText";
import { AboutWelcomeUtils } from "../../lib/aboutwelcome-utils";
import { MultiStageScreen } from "./MultiStageScreen";
import { MultiStageProtonScreen } from "./MultiStageProtonScreen";
import {
BASE_PARAMS,
addUtmParams,
@ -108,7 +108,7 @@ export const MultiStageAboutWelcome = props => {
return (
<React.Fragment>
<div className={`outer-wrapper onboardingContainer`}>
<div className={`outer-wrapper onboardingContainer ${props.design}`}>
{props.screens.map(screen => {
return index === screen.order ? (
<WelcomeScreen
@ -125,6 +125,7 @@ export const MultiStageAboutWelcome = props => {
activeTheme={activeTheme}
initialTheme={initialTheme}
setActiveTheme={setActiveTheme}
design={props.design}
/>
) : null;
})}
@ -133,6 +134,39 @@ export const MultiStageAboutWelcome = props => {
);
};
export const SecondaryCTA = props => {
let targetElement = props.position
? `secondary_button_${props.position}`
: `secondary_button`;
return (
<div
className={
props.position ? `secondary-cta ${props.position}` : "secondary-cta"
}
>
<Localized text={props.content[targetElement].text}>
<span />
</Localized>
<Localized text={props.content[targetElement].label}>
<button
className="secondary"
value={targetElement}
onClick={props.handleAction}
/>
</Localized>
</div>
);
};
export const StepsIndicator = props => {
let steps = [];
for (let i = 0; i < props.totalNumberOfScreens; i++) {
let className = i === props.order ? "current" : "";
steps.push(<div key={i} className={`indicator ${className}`} />);
}
return steps;
};
export class WelcomeScreen extends React.PureComponent {
constructor(props) {
super(props);
@ -230,242 +264,36 @@ export class WelcomeScreen extends React.PureComponent {
}
}
renderSecondaryCTA(position) {
let targetElement = position
? `secondary_button_${position}`
: `secondary_button`;
return (
<div className={position ? `secondary-cta ${position}` : "secondary-cta"}>
<Localized text={this.props.content[targetElement].text}>
<span />
</Localized>
<Localized text={this.props.content[targetElement].label}>
<button
className="secondary"
value={targetElement}
onClick={this.handleAction}
/>
</Localized>
</div>
);
}
renderTiles() {
switch (this.props.content.tiles.type) {
case "topsites":
return this.props.topSites && this.props.topSites.data ? (
<div
className={`tiles-container ${
this.props.content.tiles.info ? "info" : ""
}`}
>
<div
className="tiles-topsites-section"
name="topsites-section"
id="topsites-section"
aria-labelledby="helptext"
role="region"
>
{this.props.topSites.data
.slice(0, 5)
.map(({ icon, label, title }) => (
<div
className="site"
key={icon + label}
aria-label={title ? title : label}
role="img"
>
<div
className="icon"
style={
icon
? {
backgroundColor: "transparent",
backgroundImage: `url(${icon})`,
}
: {}
}
>
{icon ? "" : label && label[0].toUpperCase()}
</div>
{this.props.content.tiles.showTitles && (
<div className="host">{title || label}</div>
)}
</div>
))}
</div>
</div>
) : null;
case "theme":
return this.props.content.tiles.data ? (
<div className="tiles-theme-container">
<div>
<fieldset className="tiles-theme-section">
<Localized text={this.props.content.subtitle}>
<legend className="sr-only" />
</Localized>
{this.props.content.tiles.data.map(
({ theme, label, tooltip, description }) => (
<Localized
key={theme + label}
text={typeof tooltip === "object" ? tooltip : {}}
>
<label
className={`theme${
theme === this.props.activeTheme ? " selected" : ""
}`}
title={theme + label}
>
<Localized
text={
typeof description === "object" ? description : {}
}
>
<input
type="radio"
value={theme}
name="theme"
checked={theme === this.props.activeTheme}
className="sr-only input"
onClick={this.handleAction}
data-l10n-attrs="aria-description"
/>
</Localized>
<div className={`icon ${theme}`} />
{label && (
<Localized text={label}>
<div className="text" />
</Localized>
)}
</label>
</Localized>
)
)}
</fieldset>
</div>
</div>
) : null;
case "video":
return this.props.content.tiles.source ? (
<div
className={`tiles-media-section ${this.props.content.tiles.media_type}`}
>
<div className="fade" />
<video
className="media"
autoPlay="true"
loop="true"
muted="true"
src={
AboutWelcomeUtils.hasDarkMode()
? this.props.content.tiles.source.dark
: this.props.content.tiles.source.default
}
/>
</div>
) : null;
case "image":
return this.props.content.tiles.source ? (
<div className={`${this.props.content.tiles.media_type}`}>
<img
src={
AboutWelcomeUtils.hasDarkMode() &&
this.props.content.tiles.source.dark
? this.props.content.tiles.source.dark
: this.props.content.tiles.source.default
}
role="presentation"
alt=""
/>
</div>
) : null;
}
return null;
}
renderStepsIndicator() {
let steps = [];
for (let i = 0; i < this.props.totalNumberOfScreens; i++) {
let className = i === this.props.order ? "current" : "";
steps.push(<div key={i} className={`indicator ${className}`} />);
}
return steps;
}
renderHelpText() {
return (
<HelpText
text={this.props.content.help_text.text}
position={this.props.content.help_text.position}
hasImg={this.props.content.help_text.img}
/>
);
}
render() {
// Use the provided content or switch to an alternate one.
const { content, topSites } = this.props;
let newContent = content;
if (content[this.state.alternateContent]) {
Object.assign(content, content[this.state.alternateContent]);
newContent = {
...content,
...content[this.state.alternateContent],
};
}
const showImportableSitesDisclaimer =
content.tiles &&
content.tiles.type === "topsites" &&
topSites &&
topSites.showImportable;
return (
<main className={`screen ${this.props.id}`}>
{content.secondary_button_top ? this.renderSecondaryCTA("top") : null}
<div
className={`brand-logo ${
content.secondary_button_top ? "cta-top" : ""
}`}
if (this.props.design === "proton") {
return (
<MultiStageProtonScreen
content={newContent}
id={this.props.id}
handleAction={this.handleAction}
/>
<div className="welcome-text">
<Zap hasZap={content.zap} text={content.title} />
<Localized text={content.subtitle}>
<h2 />
</Localized>
</div>
{content.tiles ? this.renderTiles() : null}
<div>
<Localized
text={content.primary_button ? content.primary_button.label : null}
>
<button
className="primary"
value="primary_button"
onClick={this.handleAction}
/>
</Localized>
</div>
{content.help_text && content.help_text.position === "default"
? this.renderHelpText()
: null}
{content.secondary_button ? this.renderSecondaryCTA() : null}
<nav
className={
(content.help_text && content.help_text.position === "footer") ||
showImportableSitesDisclaimer
? "steps has-helptext"
: "steps"
}
data-l10n-id={"onboarding-welcome-steps-indicator"}
data-l10n-args={`{"current": ${parseInt(this.props.order, 10) +
1}, "total": ${this.props.totalNumberOfScreens}}`}
>
{/* These empty elements are here to help trigger the nav for screen readers. */}
<br />
<p />
{this.renderStepsIndicator()}
</nav>
{(content.help_text && content.help_text.position === "footer") ||
showImportableSitesDisclaimer
? this.renderHelpText()
: null}
</main>
);
}
return (
<MultiStageScreen
content={newContent}
id={this.props.id}
order={this.props.order}
topSites={topSites}
activeTheme={this.props.activeTheme}
totalNumberOfScreens={this.props.totalNumberOfScreens}
handleAction={this.handleAction}
/>
);
}
}

Просмотреть файл

@ -0,0 +1,36 @@
/* 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/. */
import React from "react";
import { Localized } from "./MSLocalized";
export class MultiStageProtonScreen extends React.PureComponent {
render() {
const { content } = this.props;
return (
<main className={`screen ${this.props.id}`}>
<div className="welcome-text">
<Localized text={content.title}>
<h1 />
</Localized>
<Localized text={content.subtitle}>
<h2 />
</Localized>
</div>
<div>
<Localized
text={content.primary_button ? content.primary_button.label : null}
>
<button
className="primary"
value="primary_button"
onClick={this.props.handleAction}
/>
</Localized>
</div>
</main>
);
}
}

Просмотреть файл

@ -0,0 +1,230 @@
/* 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/. */
import React from "react";
import { AboutWelcomeUtils } from "../../lib/aboutwelcome-utils";
import { Localized } from "./MSLocalized";
import { Zap } from "./Zap";
import { HelpText } from "./HelpText";
import { SecondaryCTA, StepsIndicator } from "./MultiStageAboutWelcome";
export class MultiStageScreen extends React.PureComponent {
renderTiles() {
switch (this.props.content.tiles.type) {
case "topsites":
return this.props.topSites && this.props.topSites.data ? (
<div
className={`tiles-container ${
this.props.content.tiles.info ? "info" : ""
}`}
>
<div
className="tiles-topsites-section"
name="topsites-section"
id="topsites-section"
aria-labelledby="helptext"
role="region"
>
{this.props.topSites.data
.slice(0, 5)
.map(({ icon, label, title }) => (
<div
className="site"
key={icon + label}
aria-label={title ? title : label}
role="img"
>
<div
className="icon"
style={
icon
? {
backgroundColor: "transparent",
backgroundImage: `url(${icon})`,
}
: {}
}
>
{icon ? "" : label && label[0].toUpperCase()}
</div>
{this.props.content.tiles.showTitles && (
<div className="host">{title || label}</div>
)}
</div>
))}
</div>
</div>
) : null;
case "theme":
return this.props.content.tiles.data ? (
<div className="tiles-theme-container">
<div>
<fieldset className="tiles-theme-section">
<Localized text={this.props.content.subtitle}>
<legend className="sr-only" />
</Localized>
{this.props.content.tiles.data.map(
({ theme, label, tooltip, description }) => (
<Localized
key={theme + label}
text={typeof tooltip === "object" ? tooltip : {}}
>
<label
className={`theme${
theme === this.props.activeTheme ? " selected" : ""
}`}
title={theme + label}
>
<Localized
text={
typeof description === "object" ? description : {}
}
>
<input
type="radio"
value={theme}
name="theme"
checked={theme === this.props.activeTheme}
className="sr-only input"
onClick={this.props.handleAction}
data-l10n-attrs="aria-description"
/>
</Localized>
<div className={`icon ${theme}`} />
{label && (
<Localized text={label}>
<div className="text" />
</Localized>
)}
</label>
</Localized>
)
)}
</fieldset>
</div>
</div>
) : null;
case "video":
return this.props.content.tiles.source ? (
<div
className={`tiles-media-section ${this.props.content.tiles.media_type}`}
>
<div className="fade" />
<video
className="media"
autoPlay="true"
loop="true"
muted="true"
src={
AboutWelcomeUtils.hasDarkMode()
? this.props.content.tiles.source.dark
: this.props.content.tiles.source.default
}
/>
</div>
) : null;
case "image":
return this.props.content.tiles.source ? (
<div className={`${this.props.content.tiles.media_type}`}>
<img
src={
AboutWelcomeUtils.hasDarkMode() &&
this.props.content.tiles.source.dark
? this.props.content.tiles.source.dark
: this.props.content.tiles.source.default
}
role="presentation"
alt=""
/>
</div>
) : null;
}
return null;
}
render() {
const { content, topSites } = this.props;
const showImportableSitesDisclaimer =
content.tiles &&
content.tiles.type === "topsites" &&
topSites &&
topSites.showImportable;
return (
<main className={`screen ${this.props.id}`}>
{content.secondary_button_top ? (
<SecondaryCTA
content={content}
handleAction={this.props.handleAction}
position="top"
/>
) : null}
<div
className={`brand-logo ${
content.secondary_button_top ? "cta-top" : ""
}`}
/>
<div className="welcome-text">
<Zap hasZap={content.zap} text={content.title} />
<Localized text={content.subtitle}>
<h2 />
</Localized>
</div>
{content.tiles ? this.renderTiles() : null}
<div>
<Localized
text={content.primary_button ? content.primary_button.label : null}
>
<button
className="primary"
value="primary_button"
onClick={this.props.handleAction}
/>
</Localized>
</div>
{content.help_text && content.help_text.position === "default" ? (
<HelpText
text={content.help_text.text}
position={content.help_text.position}
hasImg={content.help_text.img}
/>
) : null}
{content.secondary_button ? (
<SecondaryCTA
content={content}
handleAction={this.props.handleAction}
/>
) : null}
<nav
className={
(content.help_text && content.help_text.position === "footer") ||
showImportableSitesDisclaimer
? "steps has-helptext"
: "steps"
}
data-l10n-id={"onboarding-welcome-steps-indicator"}
data-l10n-args={`{"current": ${parseInt(this.props.order, 10) +
1}, "total": ${this.props.totalNumberOfScreens}}`}
>
{/* These empty elements are here to help trigger the nav for screen readers. */}
<br />
<p />
<StepsIndicator
order={this.props.order}
totalNumberOfScreens={this.props.totalNumberOfScreens}
/>
</nav>
{(content.help_text && content.help_text.position === "footer") ||
showImportableSitesDisclaimer ? (
<HelpText
text={content.help_text.text}
position={content.help_text.position}
hasImg={content.help_text.img}
/>
) : null}
</main>
);
}
}

Просмотреть файл

@ -191,7 +191,7 @@ module.exports = function(config) {
"content-src/aboutwelcome/**/*.jsx": {
statements: 62,
lines: 60,
functions: 83,
functions: 75,
branches: 50,
},
"content-src/components/**/*.jsx": {

Просмотреть файл

@ -0,0 +1,20 @@
import { MultiStageProtonScreen } from "content-src/aboutwelcome/components/MultiStageProtonScreen";
import React from "react";
import { mount } from "enzyme";
describe("MultiStageAboutWelcomeProton module", () => {
describe("MultiStageAWProton component", () => {
it("should render MultiStageProton Screen", () => {
const SCREEN_PROPS = {
content: {
title: "test title",
subtitle: "test subtitle",
},
};
const wrapper = mount(<MultiStageProtonScreen {...SCREEN_PROPS} />);
assert.ok(wrapper.exists());
assert.equal(wrapper.find("h1").text(), "test title");
assert.equal(wrapper.find("h2").text(), "test subtitle");
});
});
});

Просмотреть файл

@ -1,8 +1,11 @@
import { GlobalOverrider } from "test/unit/utils";
import {
MultiStageAboutWelcome,
SecondaryCTA,
StepsIndicator,
WelcomeScreen,
} from "content-src/aboutwelcome/components/MultiStageAboutWelcome";
import { MultiStageScreen } from "content-src/aboutwelcome/components/MultiStageScreen";
import React from "react";
import { shallow, mount } from "enzyme";
import { AboutWelcomeDefaults } from "aboutwelcome/lib/AboutWelcomeDefaults.jsm";
@ -30,6 +33,9 @@ describe("MultiStageAboutWelcome module", () => {
AWSendEventTelemetry: () => {},
AWWaitForRegionChange: () => Promise.resolve(),
AWGetRegion: () => Promise.resolve(),
AWIsDefaultBrowser: () => Promise.resolve("true"),
AWWaitForMigrationClose: () => Promise.resolve(),
AWSelectTheme: () => Promise.resolve(),
});
sandbox = sinon.createSandbox();
});
@ -131,6 +137,31 @@ describe("MultiStageAboutWelcome module", () => {
assert.ok(wrapper.exists());
});
it("should render secondary.top button", () => {
let SCREEN_PROPS = {
content: {
title: "Step",
secondary_button_top: {
text: "test",
label: "test label",
},
},
position: "top",
};
const wrapper = mount(<SecondaryCTA {...SCREEN_PROPS} />);
assert.ok(wrapper.find("div.secondary_button_top"));
});
it("should render steps indicator", () => {
let SCREEN_PROPS = {
totalNumberOfScreens: 1,
order: 0,
};
<StepsIndicator {...SCREEN_PROPS} />;
const wrapper = mount(<StepsIndicator {...SCREEN_PROPS} />);
assert.ok(wrapper.find("div.indicator"));
});
it("should have a primary, secondary and secondary.top button in the rendered input", () => {
const wrapper = mount(<WelcomeScreen {...GET_STARTED_SCREEN_PROPS} />);
assert.ok(wrapper.find(".primary"));
@ -140,6 +171,70 @@ describe("MultiStageAboutWelcome module", () => {
);
});
});
describe("multistagescreen tiles", () => {
let SCREEN_PROPS = {
content: {
title: "test title",
},
totalNumberOfScreens: 1,
order: 0,
id: "test",
topSites: {
data: [],
},
};
it("should render multistage Screen", () => {
const wrapper = mount(<MultiStageScreen {...SCREEN_PROPS} />);
assert.ok(wrapper.exists());
});
it("no image displayed without source", () => {
SCREEN_PROPS.content.tiles = {
type: "image",
media_type: "test-img",
};
const wrapper = mount(<MultiStageScreen {...SCREEN_PROPS} />);
assert.isFalse(wrapper.find("div.test-img").exists());
});
it("should have image displayed with source", () => {
SCREEN_PROPS.content.tiles = {
type: "image",
media_type: "test-img",
source: {
default: "",
},
};
const wrapper = mount(<MultiStageScreen {...SCREEN_PROPS} />);
assert.ok(wrapper.find("div.test-img").exists());
});
it("should have video container displayed", () => {
SCREEN_PROPS.content.tiles = {
type: "video",
media_type: "test-video",
source: {
default: "",
},
};
const wrapper = mount(<MultiStageScreen {...SCREEN_PROPS} />);
assert.ok(wrapper.find("div.test-video").exists());
});
it("should have topsites section displayed", () => {
SCREEN_PROPS.content.tiles = {
type: "topsites",
};
const wrapper = mount(<MultiStageScreen {...SCREEN_PROPS} />);
assert.ok(wrapper.find("div.tiles-topsites-section").exists());
});
it("should have theme container displayed", () => {
SCREEN_PROPS.content.tiles = {
type: "theme",
data: [],
};
const wrapper = mount(<MultiStageScreen {...SCREEN_PROPS} />);
assert.ok(wrapper.find("div.tiles-theme-container").exists());
});
});
describe("theme screen", () => {
const themeScreen = DEFAULT_WELCOME_CONTENT.screens.find(screen => {
return screen.id === "AW_CHOOSE_THEME";
@ -165,7 +260,7 @@ describe("MultiStageAboutWelcome module", () => {
});
it("should select this.props.activeTheme in the rendered input", () => {
const wrapper = shallow(<WelcomeScreen {...THEME_SCREEN_PROPS} />);
const wrapper = shallow(<MultiStageScreen {...THEME_SCREEN_PROPS} />);
const selectedThemeInput = wrapper.find(".theme.selected input");
assert.strictEqual(
@ -175,7 +270,7 @@ describe("MultiStageAboutWelcome module", () => {
});
it("should check this.props.activeTheme in the rendered input", () => {
const wrapper = shallow(<WelcomeScreen {...THEME_SCREEN_PROPS} />);
const wrapper = shallow(<MultiStageScreen {...THEME_SCREEN_PROPS} />);
const selectedThemeInput = wrapper.find(".theme input[checked=true]");
assert.strictEqual(