зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1637079 - Initial multi stage about:welcome layout r=k88hudson
Differential Revision: https://phabricator.services.mozilla.com/D74811
This commit is contained in:
Родитель
656bed86b0
Коммит
d2bfedea15
|
@ -1327,6 +1327,8 @@ pref("trailhead.firstrun.branches", "join-dynamic");
|
|||
|
||||
// Separate about welcome
|
||||
pref("browser.aboutwelcome.enabled", true);
|
||||
// Used for switching simplified 3 cards welcome to multistage welcome
|
||||
pref("browser.aboutwelcome.overrideContent", "");
|
||||
|
||||
// The pref that controls if the What's New panel is enabled.
|
||||
pref("browser.messaging-system.whatsNewPanel.enabled", true);
|
||||
|
|
|
@ -39,6 +39,7 @@ module.exports = {
|
|||
// These files use fluent-dom to insert content
|
||||
files: [
|
||||
"content-src/aboutwelcome/components/HeroText.jsx",
|
||||
"content-src/aboutwelcome/components/MultiStageAboutWelcome.jsx",
|
||||
"content-src/asrouter/templates/OnboardingMessage/**",
|
||||
"content-src/asrouter/templates/FirstRun/**",
|
||||
"content-src/asrouter/templates/Trailhead/**",
|
||||
|
|
|
@ -21,6 +21,25 @@ XPCOMUtils.defineLazyGetter(this, "log", () => {
|
|||
return new Logger("AboutWelcomeChild");
|
||||
});
|
||||
|
||||
function _parseOverrideContent(value) {
|
||||
let result = {};
|
||||
try {
|
||||
result = value ? JSON.parse(value) : {};
|
||||
} catch (e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
this,
|
||||
"multiStageAboutWelcomeContent",
|
||||
"browser.aboutwelcome.overrideContent",
|
||||
"",
|
||||
null,
|
||||
_parseOverrideContent
|
||||
);
|
||||
|
||||
class AboutWelcomeChild extends JSWindowActorChild {
|
||||
actorCreated() {
|
||||
this.exportFunctions();
|
||||
|
@ -73,6 +92,12 @@ class AboutWelcomeChild extends JSWindowActorChild {
|
|||
defineAs: "AWGetStartupData",
|
||||
});
|
||||
|
||||
// For local dev, checks for JSON content inside pref browser.aboutwelcome.overrideContent
|
||||
// that is used to override default 3 cards welcome UI with multistage welcome
|
||||
Cu.exportFunction(this.AWGetMultiStageScreens.bind(this), window, {
|
||||
defineAs: "AWGetMultiStageScreens",
|
||||
});
|
||||
|
||||
Cu.exportFunction(this.AWGetFxAMetricsFlowURI.bind(this), window, {
|
||||
defineAs: "AWGetFxAMetricsFlowURI",
|
||||
});
|
||||
|
@ -92,6 +117,16 @@ class AboutWelcomeChild extends JSWindowActorChild {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send multistage welcome JSON data read from aboutwelcome.overrideConetent pref to page
|
||||
*/
|
||||
AWGetMultiStageScreens() {
|
||||
return Cu.cloneInto(
|
||||
multiStageAboutWelcomeContent || {},
|
||||
this.contentWindow
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send initial data to page including experiment information
|
||||
*/
|
||||
|
|
|
@ -100,10 +100,11 @@ __webpack_require__.r(__webpack_exports__);
|
|||
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
|
||||
/* 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_HeroText__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3);
|
||||
/* harmony import */ var _components_FxCards__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5);
|
||||
/* harmony import */ var _components_MSLocalized__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(4);
|
||||
/* harmony import */ var _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(8);
|
||||
/* harmony import */ var _components_MultiStageAboutWelcome__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3);
|
||||
/* harmony import */ var _components_HeroText__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(6);
|
||||
/* harmony import */ var _components_FxCards__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(7);
|
||||
/* harmony import */ var _components_MSLocalized__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(4);
|
||||
/* harmony import */ var _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(5);
|
||||
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
|
||||
|
@ -116,6 +117,7 @@ function _extends() { _extends = Object.assign || function (target) { for (var i
|
|||
|
||||
|
||||
|
||||
|
||||
class AboutWelcome extends react__WEBPACK_IMPORTED_MODULE_0___default.a.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
@ -136,6 +138,8 @@ class AboutWelcome extends react__WEBPACK_IMPORTED_MODULE_0___default.a.PureComp
|
|||
componentDidMount() {
|
||||
if (this.props.experiment && this.props.branchId) {
|
||||
this.messageId = `ABOUT_WELCOME_${this.props.experiment}_${this.props.branchId}`.toUpperCase();
|
||||
} else if (this.props.id && this.props.screens) {
|
||||
this.messageId = this.props.id;
|
||||
}
|
||||
|
||||
this.fetchFxAFlowUri();
|
||||
|
@ -149,7 +153,7 @@ class AboutWelcome extends react__WEBPACK_IMPORTED_MODULE_0___default.a.PureComp
|
|||
}
|
||||
|
||||
handleStartBtnClick() {
|
||||
_lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_5__["AboutWelcomeUtils"].handleUserAction(this.props.startButton.action);
|
||||
_lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_6__["AboutWelcomeUtils"].handleUserAction(this.props.startButton.action);
|
||||
const ping = {
|
||||
event: "CLICK_BUTTON",
|
||||
event_context: {
|
||||
|
@ -165,21 +169,31 @@ class AboutWelcome extends react__WEBPACK_IMPORTED_MODULE_0___default.a.PureComp
|
|||
render() {
|
||||
const {
|
||||
props
|
||||
} = this;
|
||||
} = this; // TBD: Refactor to redirect based off template value
|
||||
// inside props.template
|
||||
// Create SimpleAboutWelcome that renders default about welcome
|
||||
// See Bug 1638087
|
||||
|
||||
if (props.screens) {
|
||||
return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_components_MultiStageAboutWelcome__WEBPACK_IMPORTED_MODULE_2__["MultiStageAboutWelcome"], {
|
||||
screens: props.screens
|
||||
});
|
||||
}
|
||||
|
||||
let UTMTerm = this.props.experiment && this.props.branchId ? `${this.props.experiment}-${this.props.branchId}` : "default";
|
||||
return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
|
||||
className: "outer-wrapper welcomeContainer"
|
||||
}, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
|
||||
className: "welcomeContainerInner"
|
||||
}, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("main", null, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_components_HeroText__WEBPACK_IMPORTED_MODULE_2__["HeroText"], {
|
||||
}, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("main", null, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_components_HeroText__WEBPACK_IMPORTED_MODULE_3__["HeroText"], {
|
||||
title: props.title,
|
||||
subtitle: props.subtitle
|
||||
}), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_components_FxCards__WEBPACK_IMPORTED_MODULE_3__["FxCards"], {
|
||||
}), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_components_FxCards__WEBPACK_IMPORTED_MODULE_4__["FxCards"], {
|
||||
cards: props.cards,
|
||||
metricsFlowUri: this.state.metricsFlowUri,
|
||||
sendTelemetry: window.AWSendEventTelemetry,
|
||||
utm_term: UTMTerm
|
||||
}), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_components_MSLocalized__WEBPACK_IMPORTED_MODULE_4__["Localized"], {
|
||||
}), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_components_MSLocalized__WEBPACK_IMPORTED_MODULE_5__["Localized"], {
|
||||
text: props.startButton.label
|
||||
}, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("button", {
|
||||
className: "start-button",
|
||||
|
@ -189,14 +203,20 @@ class AboutWelcome extends react__WEBPACK_IMPORTED_MODULE_0___default.a.PureComp
|
|||
|
||||
}
|
||||
|
||||
AboutWelcome.defaultProps = _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_5__["DEFAULT_WELCOME_CONTENT"];
|
||||
AboutWelcome.defaultProps = _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_6__["DEFAULT_WELCOME_CONTENT"];
|
||||
|
||||
async function mount() {
|
||||
const {
|
||||
slug,
|
||||
branch
|
||||
} = await window.AWGetStartupData();
|
||||
const settings = branch && branch.value ? branch.value : {};
|
||||
let settings = branch && branch.value ? branch.value : {};
|
||||
|
||||
if (!(branch && branch.value)) {
|
||||
// Check for override content in pref browser.aboutwelcome.overrideContent
|
||||
settings = await window.AWGetMultiStageScreens();
|
||||
}
|
||||
|
||||
react_dom__WEBPACK_IMPORTED_MODULE_1___default.a.render(react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(AboutWelcome, _extends({
|
||||
experiment: slug,
|
||||
branchId: branch && branch.slug
|
||||
|
@ -223,24 +243,48 @@ module.exports = ReactDOM;
|
|||
|
||||
"use strict";
|
||||
__webpack_require__.r(__webpack_exports__);
|
||||
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HeroText", function() { return HeroText; });
|
||||
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MultiStageAboutWelcome", function() { return MultiStageAboutWelcome; });
|
||||
/* 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 _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(5);
|
||||
/* 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 HeroText = props => {
|
||||
return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react__WEBPACK_IMPORTED_MODULE_0___default.a.Fragment, null, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__["Localized"], {
|
||||
text: props.title
|
||||
}, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("h1", {
|
||||
className: "welcome-title"
|
||||
})), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__["Localized"], {
|
||||
text: props.subtitle
|
||||
}, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("h2", {
|
||||
className: "welcome-subtitle"
|
||||
|
||||
const MultiStageAboutWelcome = props => {
|
||||
const [index, setScreenIndex] = Object(react__WEBPACK_IMPORTED_MODULE_0__["useState"])(0); // Transition to next screen, opening about:home on last screen button CTA
|
||||
|
||||
const handleTransition = index < props.screens.length ? Object(react__WEBPACK_IMPORTED_MODULE_0__["useCallback"])(() => setScreenIndex(prevState => prevState + 1), []) : _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__["AboutWelcomeUtils"].handleUserAction({
|
||||
type: "OPEN_ABOUT_PAGE",
|
||||
data: {
|
||||
args: "home",
|
||||
where: "current"
|
||||
}
|
||||
});
|
||||
return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react__WEBPACK_IMPORTED_MODULE_0___default.a.Fragment, null, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
|
||||
className: `welcomeCardGrid`
|
||||
}, props.screens.map(screen => {
|
||||
return index === screen.order ? react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(WelcomeScreen, {
|
||||
key: screen.id,
|
||||
id: screen.id,
|
||||
content: screen.content,
|
||||
navigate: handleTransition
|
||||
}) : null;
|
||||
})));
|
||||
};
|
||||
|
||||
const WelcomeScreen = props => {
|
||||
return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
|
||||
className: `${props.id}`
|
||||
}, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__["Localized"], {
|
||||
text: props.content.title
|
||||
}, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("h1", null)), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__["Localized"], {
|
||||
text: props.content.primary_button.label
|
||||
}, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("button", {
|
||||
onClick: props.navigate
|
||||
})));
|
||||
};
|
||||
|
||||
|
@ -305,14 +349,164 @@ const Localized = ({
|
|||
/* 5 */
|
||||
/***/ (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; });
|
||||
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DEFAULT_WELCOME_CONTENT", function() { return DEFAULT_WELCOME_CONTENT; });
|
||||
/* 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 AboutWelcomeUtils = {
|
||||
handleUserAction(action) {
|
||||
switch (action.type) {
|
||||
case "OPEN_ABOUT_PAGE":
|
||||
case "OPEN_AWESOME_BAR":
|
||||
case "OPEN_PRIVATE_BROWSER_WINDOW":
|
||||
case "SHOW_MIGRATION_WIZARD":
|
||||
window.AWSendToParent("SPECIAL_ACTION", action);
|
||||
break;
|
||||
|
||||
case "OPEN_URL":
|
||||
window.open(action.data.args);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
sendEvent(type, detail) {
|
||||
document.dispatchEvent(new CustomEvent(`AWPage:${type}`, {
|
||||
bubbles: true,
|
||||
detail
|
||||
}));
|
||||
}
|
||||
|
||||
};
|
||||
const DEFAULT_WELCOME_CONTENT = {
|
||||
title: {
|
||||
string_id: "onboarding-welcome-header"
|
||||
},
|
||||
startButton: {
|
||||
label: {
|
||||
string_id: "onboarding-start-browsing-button-label"
|
||||
},
|
||||
message_id: "START_BROWSING_BUTTON",
|
||||
action: {
|
||||
type: "OPEN_AWESOME_BAR"
|
||||
}
|
||||
},
|
||||
cards: [{
|
||||
content: {
|
||||
title: {
|
||||
string_id: "onboarding-data-sync-title"
|
||||
},
|
||||
text: {
|
||||
string_id: "onboarding-data-sync-text2"
|
||||
},
|
||||
icon: "devices",
|
||||
primary_button: {
|
||||
label: {
|
||||
string_id: "onboarding-data-sync-button2"
|
||||
},
|
||||
action: {
|
||||
type: "OPEN_URL",
|
||||
addFlowParams: true,
|
||||
data: {
|
||||
args: "https://accounts.firefox.com/?service=sync&action=email&context=fx_desktop_v3&entrypoint=activity-stream-firstrun&style=trailhead",
|
||||
where: "tabshifted"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
id: "TRAILHEAD_CARD_2",
|
||||
order: 1,
|
||||
blockOnClick: false
|
||||
}, {
|
||||
content: {
|
||||
title: {
|
||||
string_id: "onboarding-firefox-monitor-title"
|
||||
},
|
||||
text: {
|
||||
string_id: "onboarding-firefox-monitor-text2"
|
||||
},
|
||||
icon: "ffmonitor",
|
||||
primary_button: {
|
||||
label: {
|
||||
string_id: "onboarding-firefox-monitor-button"
|
||||
},
|
||||
action: {
|
||||
type: "OPEN_URL",
|
||||
data: {
|
||||
args: "https://monitor.firefox.com/",
|
||||
where: "tabshifted"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
id: "TRAILHEAD_CARD_3",
|
||||
order: 2,
|
||||
blockOnClick: false
|
||||
}, {
|
||||
content: {
|
||||
title: {
|
||||
string_id: "onboarding-browse-privately-title"
|
||||
},
|
||||
text: {
|
||||
string_id: "onboarding-browse-privately-text"
|
||||
},
|
||||
icon: "private",
|
||||
primary_button: {
|
||||
label: {
|
||||
string_id: "onboarding-browse-privately-button"
|
||||
},
|
||||
action: {
|
||||
type: "OPEN_PRIVATE_BROWSER_WINDOW"
|
||||
}
|
||||
}
|
||||
},
|
||||
id: "TRAILHEAD_CARD_4",
|
||||
order: 3,
|
||||
blockOnClick: true
|
||||
}]
|
||||
};
|
||||
|
||||
/***/ }),
|
||||
/* 6 */
|
||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
__webpack_require__.r(__webpack_exports__);
|
||||
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HeroText", function() { return HeroText; });
|
||||
/* 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 HeroText = props => {
|
||||
return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react__WEBPACK_IMPORTED_MODULE_0___default.a.Fragment, null, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__["Localized"], {
|
||||
text: props.title
|
||||
}, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("h1", {
|
||||
className: "welcome-title"
|
||||
})), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__["Localized"], {
|
||||
text: props.subtitle
|
||||
}, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("h2", {
|
||||
className: "welcome-subtitle"
|
||||
})));
|
||||
};
|
||||
|
||||
/***/ }),
|
||||
/* 7 */
|
||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
__webpack_require__.r(__webpack_exports__);
|
||||
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FxCards", function() { return FxCards; });
|
||||
/* 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 _asrouter_templates_FirstRun_addUtmParams__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6);
|
||||
/* harmony import */ var _asrouter_templates_OnboardingMessage_OnboardingMessage__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(7);
|
||||
/* harmony import */ var _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(8);
|
||||
/* harmony import */ var _asrouter_templates_FirstRun_addUtmParams__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(8);
|
||||
/* harmony import */ var _asrouter_templates_OnboardingMessage_OnboardingMessage__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(9);
|
||||
/* harmony import */ var _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5);
|
||||
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
|
||||
|
@ -422,7 +616,7 @@ class FxCards extends react__WEBPACK_IMPORTED_MODULE_0___default.a.PureComponent
|
|||
}
|
||||
|
||||
/***/ }),
|
||||
/* 6 */
|
||||
/* 8 */
|
||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
@ -463,7 +657,7 @@ function addUtmParams(url, utmTerm) {
|
|||
}
|
||||
|
||||
/***/ }),
|
||||
/* 7 */
|
||||
/* 9 */
|
||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
@ -527,127 +721,5 @@ class OnboardingCard extends react__WEBPACK_IMPORTED_MODULE_0___default.a.PureCo
|
|||
|
||||
}
|
||||
|
||||
/***/ }),
|
||||
/* 8 */
|
||||
/***/ (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; });
|
||||
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DEFAULT_WELCOME_CONTENT", function() { return DEFAULT_WELCOME_CONTENT; });
|
||||
/* 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 AboutWelcomeUtils = {
|
||||
handleUserAction(action) {
|
||||
switch (action.type) {
|
||||
case "OPEN_AWESOME_BAR":
|
||||
case "OPEN_PRIVATE_BROWSER_WINDOW":
|
||||
case "SHOW_MIGRATION_WIZARD":
|
||||
window.AWSendToParent("SPECIAL_ACTION", action);
|
||||
break;
|
||||
|
||||
case "OPEN_URL":
|
||||
window.open(action.data.args);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
sendEvent(type, detail) {
|
||||
document.dispatchEvent(new CustomEvent(`AWPage:${type}`, {
|
||||
bubbles: true,
|
||||
detail
|
||||
}));
|
||||
}
|
||||
|
||||
};
|
||||
const DEFAULT_WELCOME_CONTENT = {
|
||||
title: {
|
||||
string_id: "onboarding-welcome-header"
|
||||
},
|
||||
startButton: {
|
||||
label: {
|
||||
string_id: "onboarding-start-browsing-button-label"
|
||||
},
|
||||
message_id: "START_BROWSING_BUTTON",
|
||||
action: {
|
||||
type: "OPEN_AWESOME_BAR"
|
||||
}
|
||||
},
|
||||
cards: [{
|
||||
content: {
|
||||
title: {
|
||||
string_id: "onboarding-data-sync-title"
|
||||
},
|
||||
text: {
|
||||
string_id: "onboarding-data-sync-text2"
|
||||
},
|
||||
icon: "devices",
|
||||
primary_button: {
|
||||
label: {
|
||||
string_id: "onboarding-data-sync-button2"
|
||||
},
|
||||
action: {
|
||||
type: "OPEN_URL",
|
||||
addFlowParams: true,
|
||||
data: {
|
||||
args: "https://accounts.firefox.com/?service=sync&action=email&context=fx_desktop_v3&entrypoint=activity-stream-firstrun&style=trailhead",
|
||||
where: "tabshifted"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
id: "TRAILHEAD_CARD_2",
|
||||
order: 1,
|
||||
blockOnClick: false
|
||||
}, {
|
||||
content: {
|
||||
title: {
|
||||
string_id: "onboarding-firefox-monitor-title"
|
||||
},
|
||||
text: {
|
||||
string_id: "onboarding-firefox-monitor-text2"
|
||||
},
|
||||
icon: "ffmonitor",
|
||||
primary_button: {
|
||||
label: {
|
||||
string_id: "onboarding-firefox-monitor-button"
|
||||
},
|
||||
action: {
|
||||
type: "OPEN_URL",
|
||||
data: {
|
||||
args: "https://monitor.firefox.com/",
|
||||
where: "tabshifted"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
id: "TRAILHEAD_CARD_3",
|
||||
order: 2,
|
||||
blockOnClick: false
|
||||
}, {
|
||||
content: {
|
||||
title: {
|
||||
string_id: "onboarding-browse-privately-title"
|
||||
},
|
||||
text: {
|
||||
string_id: "onboarding-browse-privately-text"
|
||||
},
|
||||
icon: "private",
|
||||
primary_button: {
|
||||
label: {
|
||||
string_id: "onboarding-browse-privately-button"
|
||||
},
|
||||
action: {
|
||||
type: "OPEN_PRIVATE_BROWSER_WINDOW"
|
||||
}
|
||||
}
|
||||
},
|
||||
id: "TRAILHEAD_CARD_4",
|
||||
order: 3,
|
||||
blockOnClick: true
|
||||
}]
|
||||
};
|
||||
|
||||
/***/ })
|
||||
/******/ ]);
|
|
@ -121,12 +121,9 @@ body {
|
|||
margin-top: 32px;
|
||||
display: grid;
|
||||
grid-gap: 32px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.4s;
|
||||
transition-delay: 0.1s;
|
||||
grid-auto-rows: 1fr; }
|
||||
.welcomeCardGrid.show {
|
||||
opacity: 1; }
|
||||
@media (min-width: 610px) {
|
||||
.welcomeCardGrid {
|
||||
grid-template-columns: repeat(auto-fit, 224px); } }
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import { MultiStageAboutWelcome } from "./components/MultiStageAboutWelcome";
|
||||
import { HeroText } from "./components/HeroText";
|
||||
import { FxCards } from "./components/FxCards";
|
||||
import { Localized } from "./components/MSLocalized";
|
||||
|
@ -29,6 +30,8 @@ class AboutWelcome extends React.PureComponent {
|
|||
componentDidMount() {
|
||||
if (this.props.experiment && this.props.branchId) {
|
||||
this.messageId = `ABOUT_WELCOME_${this.props.experiment}_${this.props.branchId}`.toUpperCase();
|
||||
} else if (this.props.id && this.props.screens) {
|
||||
this.messageId = this.props.id;
|
||||
}
|
||||
this.fetchFxAFlowUri();
|
||||
window.AWSendEventTelemetry({
|
||||
|
@ -56,6 +59,14 @@ class AboutWelcome extends React.PureComponent {
|
|||
|
||||
render() {
|
||||
const { props } = this;
|
||||
// TBD: Refactor to redirect based off template value
|
||||
// inside props.template
|
||||
// Create SimpleAboutWelcome that renders default about welcome
|
||||
// See Bug 1638087
|
||||
if (props.screens) {
|
||||
return <MultiStageAboutWelcome screens={props.screens} />;
|
||||
}
|
||||
|
||||
let UTMTerm =
|
||||
this.props.experiment && this.props.branchId
|
||||
? `${this.props.experiment}-${this.props.branchId}`
|
||||
|
@ -88,7 +99,12 @@ AboutWelcome.defaultProps = DEFAULT_WELCOME_CONTENT;
|
|||
|
||||
async function mount() {
|
||||
const { slug, branch } = await window.AWGetStartupData();
|
||||
const settings = branch && branch.value ? branch.value : {};
|
||||
let settings = branch && branch.value ? branch.value : {};
|
||||
|
||||
if (!(branch && branch.value)) {
|
||||
// Check for override content in pref browser.aboutwelcome.overrideContent
|
||||
settings = await window.AWGetMultiStageScreens();
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<AboutWelcome
|
||||
|
|
|
@ -61,15 +61,10 @@ body {
|
|||
margin-top: 32px;
|
||||
display: grid;
|
||||
grid-gap: 32px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.4s;
|
||||
transition-delay: 0.1s;
|
||||
grid-auto-rows: 1fr;
|
||||
|
||||
&.show {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@media (min-width: $break-point-medium) {
|
||||
grid-template-columns: repeat(auto-fit, 224px);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/* 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, { useState, useCallback } from "react";
|
||||
import { Localized } from "./MSLocalized";
|
||||
import { AboutWelcomeUtils } from "../../lib/aboutwelcome-utils";
|
||||
|
||||
export const MultiStageAboutWelcome = props => {
|
||||
const [index, setScreenIndex] = useState(0);
|
||||
// Transition to next screen, opening about:home on last screen button CTA
|
||||
const handleTransition =
|
||||
index < props.screens.length
|
||||
? useCallback(() => setScreenIndex(prevState => prevState + 1), [])
|
||||
: AboutWelcomeUtils.handleUserAction({
|
||||
type: "OPEN_ABOUT_PAGE",
|
||||
data: { args: "home", where: "current" },
|
||||
});
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div className={`welcomeCardGrid`}>
|
||||
{props.screens.map(screen => {
|
||||
return index === screen.order ? (
|
||||
<WelcomeScreen
|
||||
key={screen.id}
|
||||
id={screen.id}
|
||||
content={screen.content}
|
||||
navigate={handleTransition}
|
||||
/>
|
||||
) : null;
|
||||
})}
|
||||
</div>
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
const WelcomeScreen = props => {
|
||||
return (
|
||||
<div className={`${props.id}`}>
|
||||
<Localized text={props.content.title}>
|
||||
<h1 />
|
||||
</Localized>
|
||||
<Localized text={props.content.primary_button.label}>
|
||||
<button onClick={props.navigate} />
|
||||
</Localized>
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -5,6 +5,7 @@
|
|||
export const AboutWelcomeUtils = {
|
||||
handleUserAction(action) {
|
||||
switch (action.type) {
|
||||
case "OPEN_ABOUT_PAGE":
|
||||
case "OPEN_AWESOME_BAR":
|
||||
case "OPEN_PRIVATE_BROWSER_WINDOW":
|
||||
case "SHOW_MIGRATION_WIZARD":
|
||||
|
|
|
@ -16,6 +16,7 @@ prefs =
|
|||
[browser_aboutwelcome.js]
|
||||
[browser_aboutwelcome_actors.js]
|
||||
[browser_aboutwelcome_simplified.js]
|
||||
[browser_aboutwelcome_multistage.js]
|
||||
[browser_aboutwelcome_observer.js]
|
||||
[browser_as_load_location.js]
|
||||
[browser_as_render.js]
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
"use strict";
|
||||
|
||||
const SEPARATE_ABOUT_WELCOME_PREF = "browser.aboutwelcome.enabled";
|
||||
const ABOUT_WELCOME_OVERRIDE_CONTENT_PREF =
|
||||
"browser.aboutwelcome.overrideContent";
|
||||
const TEST_MULTISTAGE_JSON =
|
||||
'{"id": "multi-stage-welcome","screens": [{"id": "AW_STEP1","order": 0,"content": {"title": "Step 1","primary_button": {"label": "Next"}}},{"id": "AW_STEP2","order": 1,"content": {"title": "Step 2","primary_button": {"label": "Next"}}},{"id": "AW_STEP3","order": 2,"content": {"title": "Step 3","primary_button": {"label": "Next"}}}]}';
|
||||
|
||||
/**
|
||||
* Sets the aboutwelcome pref to enabled simplified welcome UI
|
||||
*/
|
||||
async function setAboutWelcomePref(value) {
|
||||
return pushPrefs([SEPARATE_ABOUT_WELCOME_PREF, value]);
|
||||
}
|
||||
|
||||
async function setAboutWelcomeMultiStage(value) {
|
||||
return pushPrefs([ABOUT_WELCOME_OVERRIDE_CONTENT_PREF, value]);
|
||||
}
|
||||
|
||||
async function openAboutWelcome() {
|
||||
await setAboutWelcomePref(true);
|
||||
await setAboutWelcomeMultiStage(TEST_MULTISTAGE_JSON);
|
||||
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab(
|
||||
gBrowser,
|
||||
"about:welcome",
|
||||
true
|
||||
);
|
||||
registerCleanupFunction(() => {
|
||||
BrowserTestUtils.removeTab(tab);
|
||||
});
|
||||
return tab.linkedBrowser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup and test simplified welcome UI
|
||||
*/
|
||||
async function test_about_welcome(
|
||||
browser,
|
||||
experiment,
|
||||
expectedSelectors = [],
|
||||
unexpectedSelectors = []
|
||||
) {
|
||||
await ContentTask.spawn(
|
||||
browser,
|
||||
{ expectedSelectors, experiment, unexpectedSelectors },
|
||||
async ({
|
||||
expectedSelectors: expected,
|
||||
experiment: experimentName,
|
||||
unexpectedSelectors: unexpected,
|
||||
}) => {
|
||||
for (let selector of expected) {
|
||||
await ContentTaskUtils.waitForCondition(
|
||||
() => content.document.querySelector(selector),
|
||||
`Should render ${selector} in ${experimentName}`
|
||||
);
|
||||
}
|
||||
for (let selector of unexpected) {
|
||||
ok(
|
||||
!content.document.querySelector(selector),
|
||||
`Should not render ${selector} in ${experimentName}`
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
async function onNavigate(browser, message) {
|
||||
await ContentTask.spawn(
|
||||
browser,
|
||||
{ message },
|
||||
async ({ message: messageText }) => {
|
||||
await ContentTaskUtils.waitForCondition(
|
||||
() => content.document.querySelector("button"),
|
||||
messageText
|
||||
);
|
||||
let button = content.document.querySelector("button");
|
||||
button.click();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the multistage welcome UI rendered using TEST_MULTISTAGE_JSON
|
||||
*/
|
||||
add_task(async function test_Separate_About_Welcome_branches() {
|
||||
let browser = await openAboutWelcome();
|
||||
|
||||
await test_about_welcome(
|
||||
browser,
|
||||
"multistage step 1",
|
||||
// Expected selectors:
|
||||
["div.welcomeCardGrid", "div.AW_STEP1"],
|
||||
// Unexpected selectors:
|
||||
["div.AW_STEP2", "div.AW_STEP3"]
|
||||
);
|
||||
|
||||
await onNavigate(browser, "Step 1");
|
||||
await test_about_welcome(
|
||||
browser,
|
||||
"multistage step 2",
|
||||
// Expected selectors:
|
||||
["div.welcomeCardGrid", "div.AW_STEP2"],
|
||||
// Unexpected selectors:
|
||||
["div.AW_STEP1", "div.AW_STEP3"]
|
||||
);
|
||||
await onNavigate(browser, "Step 2");
|
||||
await test_about_welcome(
|
||||
browser,
|
||||
"multistage step 3",
|
||||
// Expected selectors:
|
||||
["div.welcomeCardGrid", "div.AW_STEP3"],
|
||||
// Unexpected selectors:
|
||||
["div.AW_STEP1", "div.AW_STEP2"]
|
||||
);
|
||||
});
|
|
@ -110,7 +110,10 @@ const SpecialMessageActions = {
|
|||
if (action.data.entrypoint) {
|
||||
aboutPageURL.search = action.data.entrypoint;
|
||||
}
|
||||
window.openTrustedLinkIn(aboutPageURL.toString(), "tab");
|
||||
window.openTrustedLinkIn(
|
||||
aboutPageURL.toString(),
|
||||
action.data.where || "tab"
|
||||
);
|
||||
break;
|
||||
case "OPEN_PREFERENCES_PAGE":
|
||||
window.openPreferences(
|
||||
|
|
|
@ -66,6 +66,12 @@ const SpecialMessageActionSchemas = {
|
|||
description: 'The about page. E.g. "welcome" for about:welcome',
|
||||
type: "string",
|
||||
},
|
||||
where: {
|
||||
default: "tab",
|
||||
description: "Where the URL is opened.",
|
||||
enum: ["current", "save", "tab", "tabshifted", "window"],
|
||||
type: "string",
|
||||
},
|
||||
entrypoint: {
|
||||
description:
|
||||
'Any optional entrypoint value that will be added to the search. E.g. "foo=bar" would result in about:welcome?foo=bar',
|
||||
|
|
Загрузка…
Ссылка в новой задаче