зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1813716 - Encapsulate aboutwelcome container and make its ID more unique. r=omc-reviewers,fxview-reviewers,sfoster,jprickett
Differential Revision: https://phabricator.services.mozilla.com/D172493
This commit is contained in:
Родитель
1a1ba61c29
Коммит
78935b829e
|
@ -49,7 +49,7 @@ function renderMultistage(ready) {
|
|||
);
|
||||
|
||||
document.body.classList.add("onboardingContainer");
|
||||
document.body.id = "root";
|
||||
document.body.id = "multi-stage-message-root";
|
||||
// This value is reported as the "page" in telemetry
|
||||
document.body.dataset.page = "spotlight";
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ const RECENTLY_CLOSED_STATE_PREF =
|
|||
const TAB_PICKUP_STATE_PREF =
|
||||
"browser.tabs.firefox-view.ui-state.tab-pickup.open";
|
||||
|
||||
const calloutId = "root";
|
||||
const calloutId = "multi-stage-message-root";
|
||||
const calloutSelector = `#${calloutId}.featureCallout`;
|
||||
const primaryButtonSelector = `#${calloutId} .primary`;
|
||||
|
||||
|
|
|
@ -28,13 +28,15 @@ __webpack_require__.r(__webpack_exports__);
|
|||
/* harmony export */ "AboutWelcomeUtils": () => (/* binding */ AboutWelcomeUtils),
|
||||
/* harmony export */ "DEFAULT_RTAMO_CONTENT": () => (/* binding */ DEFAULT_RTAMO_CONTENT)
|
||||
/* harmony export */ });
|
||||
var _document$querySelect;
|
||||
|
||||
/* 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/. */
|
||||
// If the container has a "page" data attribute, then this is
|
||||
// a Spotlight modal or Feature Callout. Otherwise, this is
|
||||
// about:welcome and we should return the current page.
|
||||
const page = document.querySelector("#root.onboardingContainer[data-page]") ? document.querySelector("#root[data-page]").dataset.page : document.location.href;
|
||||
const page = ((_document$querySelect = document.querySelector("#multi-stage-message-root.onboardingContainer[data-page]")) === null || _document$querySelect === void 0 ? void 0 : _document$querySelect.dataset.page) || document.location.href;
|
||||
const AboutWelcomeUtils = {
|
||||
handleUserAction(action) {
|
||||
window.AWSendToParent("SPECIAL_ACTION", action);
|
||||
|
@ -2200,7 +2202,7 @@ async function mount() {
|
|||
react_dom__WEBPACK_IMPORTED_MODULE_1___default().render( /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(AboutWelcome, _extends({
|
||||
messageId: messageId,
|
||||
UTMTerm: UTMTerm
|
||||
}, aboutWelcomeProps)), document.getElementById("root"));
|
||||
}, aboutWelcomeProps)), document.getElementById("multi-stage-message-root"));
|
||||
}
|
||||
|
||||
performance.mark("mount");
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<link rel="localization" href="browser/spotlight.ftl"/>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root" class="welcome-container" role="presentation">
|
||||
<div id="multi-stage-message-root" class="welcome-container" role="presentation">
|
||||
</div>
|
||||
<script src="resource://activity-stream/vendor/react.js"></script>
|
||||
<script src="resource://activity-stream/vendor/react-dom.js"></script>
|
||||
|
|
|
@ -132,7 +132,7 @@ async function mount() {
|
|||
UTMTerm={UTMTerm}
|
||||
{...aboutWelcomeProps}
|
||||
/>,
|
||||
document.getElementById("root")
|
||||
document.getElementById("multi-stage-message-root")
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,9 +5,10 @@
|
|||
// If the container has a "page" data attribute, then this is
|
||||
// a Spotlight modal or Feature Callout. Otherwise, this is
|
||||
// about:welcome and we should return the current page.
|
||||
const page = document.querySelector("#root.onboardingContainer[data-page]")
|
||||
? document.querySelector("#root[data-page]").dataset.page
|
||||
: document.location.href;
|
||||
const page =
|
||||
document.querySelector(
|
||||
"#multi-stage-message-root.onboardingContainer[data-page]"
|
||||
)?.dataset.page || document.location.href;
|
||||
|
||||
export const AboutWelcomeUtils = {
|
||||
handleUserAction(action) {
|
||||
|
|
|
@ -730,32 +730,28 @@ add_setup(async function() {
|
|||
});
|
||||
});
|
||||
|
||||
// Test Fxaccounts MetricsFlowURI
|
||||
test_newtab(
|
||||
{
|
||||
async before({ pushPrefs }) {
|
||||
await pushPrefs(["browser.aboutwelcome.enabled", true]);
|
||||
},
|
||||
test: async function test_startBrowsing() {
|
||||
add_task(async function test_FxA_metricsFlowURI() {
|
||||
let browser = await openAboutWelcome();
|
||||
|
||||
await ContentTask.spawn(browser, {}, async () => {
|
||||
Assert.ok(
|
||||
await ContentTaskUtils.waitForCondition(
|
||||
() => content.document.querySelector("div.onboardingContainer"),
|
||||
"Wait for about:welcome to load"
|
||||
);
|
||||
},
|
||||
after() {
|
||||
Assert.ok(
|
||||
FxAccounts.config.promiseMetricsFlowURI.called,
|
||||
"Stub was called"
|
||||
);
|
||||
Assert.equal(
|
||||
FxAccounts.config.promiseMetricsFlowURI.firstCall.args[0],
|
||||
"aboutwelcome",
|
||||
"Called by AboutWelcomeParent"
|
||||
);
|
||||
},
|
||||
},
|
||||
"about:welcome"
|
||||
);
|
||||
),
|
||||
"about:welcome loaded"
|
||||
);
|
||||
});
|
||||
|
||||
Assert.ok(FxAccounts.config.promiseMetricsFlowURI.called, "Stub was called");
|
||||
Assert.equal(
|
||||
FxAccounts.config.promiseMetricsFlowURI.firstCall.args[0],
|
||||
"aboutwelcome",
|
||||
"Called by AboutWelcomeParent"
|
||||
);
|
||||
|
||||
SpecialPowers.popPrefEnv();
|
||||
});
|
||||
|
||||
add_task(async function test_send_aboutwelcome_as_page_in_event_telemetry() {
|
||||
const sandbox = sinon.createSandbox();
|
||||
|
|
|
@ -7,7 +7,7 @@ const { ASRouter } = ChromeUtils.import(
|
|||
"resource://activity-stream/lib/ASRouter.jsm"
|
||||
);
|
||||
|
||||
const calloutId = "root";
|
||||
const calloutId = "multi-stage-message-root";
|
||||
const calloutSelector = `#${calloutId}.featureCallout`;
|
||||
const primaryButtonSelector = `#${calloutId} .primary`;
|
||||
const PDF_TEST_URL =
|
||||
|
@ -187,7 +187,9 @@ add_task(
|
|||
const tab2 = await openURLInNewTab(win, "about:preferences");
|
||||
tab2.focus();
|
||||
await BrowserTestUtils.waitForCondition(() => {
|
||||
return !doc.body.querySelector("#root.featureCallout");
|
||||
return !doc.body.querySelector(
|
||||
"#multi-stage-message-root.featureCallout"
|
||||
);
|
||||
});
|
||||
|
||||
ok(
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
* 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/. */
|
||||
|
||||
/*eslint-env browser*/
|
||||
|
||||
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
|
||||
|
||||
const lazy = {};
|
||||
|
@ -14,7 +12,7 @@ XPCOMUtils.defineLazyModuleGetters(lazy, {
|
|||
});
|
||||
|
||||
const TRANSITION_MS = 500;
|
||||
const CONTAINER_ID = "root";
|
||||
const CONTAINER_ID = "multi-stage-message-root";
|
||||
const BUNDLE_SRC =
|
||||
"resource://activity-stream/aboutwelcome/aboutwelcome.bundle.js";
|
||||
|
||||
|
@ -157,13 +155,12 @@ export class FeatureCallout {
|
|||
this.currentScreen = null;
|
||||
} else if (prefVal.screen !== this.currentScreen?.id) {
|
||||
this.ready = false;
|
||||
const container = this.doc.getElementById(CONTAINER_ID);
|
||||
container?.classList.add("hidden");
|
||||
this._container?.classList.add("hidden");
|
||||
this._pageEventManager?.clear();
|
||||
// wait for fade out transition
|
||||
this.win.setTimeout(async () => {
|
||||
await this._loadConfig();
|
||||
container?.remove();
|
||||
this._container?.remove();
|
||||
this._removePositionListeners();
|
||||
this.doc.querySelector(`[src="${BUNDLE_SRC}"]`)?.remove();
|
||||
await this._renderCallout();
|
||||
|
@ -174,16 +171,16 @@ export class FeatureCallout {
|
|||
handleEvent(event) {
|
||||
switch (event.type) {
|
||||
case "focus": {
|
||||
let container = this.doc.getElementById(CONTAINER_ID);
|
||||
if (!container) {
|
||||
if (!this._container) {
|
||||
return;
|
||||
}
|
||||
// If focus has fired on the feature callout window itself, or on something
|
||||
// contained in that window, ignore it, as we can't possibly place the focus
|
||||
// on it after the callout is closd.
|
||||
if (
|
||||
event.target.id === CONTAINER_ID ||
|
||||
(Node.isInstance(event.target) && container.contains(event.target))
|
||||
event.target === this._container ||
|
||||
(Node.isInstance(event.target) &&
|
||||
this._container.contains(event.target))
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
@ -198,8 +195,7 @@ export class FeatureCallout {
|
|||
if (event.key !== "Escape") {
|
||||
return;
|
||||
}
|
||||
let container = this.doc.getElementById(CONTAINER_ID);
|
||||
if (!container) {
|
||||
if (!this._container) {
|
||||
return;
|
||||
}
|
||||
let focusedElement =
|
||||
|
@ -211,7 +207,7 @@ export class FeatureCallout {
|
|||
!focusedElement ||
|
||||
focusedElement === this.doc.body ||
|
||||
focusedElement === this.browser ||
|
||||
container.contains(focusedElement)
|
||||
this._container.contains(focusedElement)
|
||||
) {
|
||||
this.win.AWSendEventTelemetry?.({
|
||||
event: "DISMISS",
|
||||
|
@ -290,31 +286,33 @@ export class FeatureCallout {
|
|||
return false;
|
||||
}
|
||||
|
||||
let container = this.doc.createElement("div");
|
||||
container.classList.add(
|
||||
"onboardingContainer",
|
||||
"featureCallout",
|
||||
"callout-arrow",
|
||||
"hidden"
|
||||
);
|
||||
container.id = CONTAINER_ID;
|
||||
// This value is reported as the "page" in about:welcome telemetry
|
||||
container.dataset.page = this.page;
|
||||
container.setAttribute(
|
||||
"aria-describedby",
|
||||
`#${CONTAINER_ID} .welcome-text`
|
||||
);
|
||||
container.tabIndex = 0;
|
||||
this._applyTheme(container);
|
||||
this.doc.body.prepend(container);
|
||||
return container;
|
||||
if (!this._container?.parentElement) {
|
||||
this._container = this.doc.createElement("div");
|
||||
this._container.classList.add(
|
||||
"onboardingContainer",
|
||||
"featureCallout",
|
||||
"callout-arrow",
|
||||
"hidden"
|
||||
);
|
||||
this._container.id = CONTAINER_ID;
|
||||
// This value is reported as the "page" in about:welcome telemetry
|
||||
this._container.dataset.page = this.page;
|
||||
this._container.setAttribute(
|
||||
"aria-describedby",
|
||||
`#${CONTAINER_ID} .welcome-text`
|
||||
);
|
||||
this._container.tabIndex = 0;
|
||||
this._applyTheme();
|
||||
this.doc.body.prepend(this._container);
|
||||
}
|
||||
return this._container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set callout's position relative to parent element
|
||||
*/
|
||||
_positionCallout() {
|
||||
const container = this.doc.getElementById(CONTAINER_ID);
|
||||
const container = this._container;
|
||||
const parentEl = this.doc.querySelector(
|
||||
this.currentScreen?.parent_selector
|
||||
);
|
||||
|
@ -727,12 +725,11 @@ export class FeatureCallout {
|
|||
delete this.featureTourProgress;
|
||||
this.ready = false;
|
||||
// wait for fade out transition
|
||||
let container = this.doc.getElementById(CONTAINER_ID);
|
||||
container?.classList.add("hidden");
|
||||
this._container?.classList.add("hidden");
|
||||
this._clearWindowFunctions();
|
||||
this.win.setTimeout(
|
||||
() => {
|
||||
container?.remove();
|
||||
this._container?.remove();
|
||||
this.renderObserver?.disconnect();
|
||||
this._removePositionListeners();
|
||||
this.doc.querySelector(`[src="${BUNDLE_SRC}"]`)?.remove();
|
||||
|
@ -961,7 +958,7 @@ export class FeatureCallout {
|
|||
|
||||
this.renderObserver = new this.win.MutationObserver(() => {
|
||||
// Check if the Feature Callout screen has loaded for the first time
|
||||
if (!this.ready && this.doc.querySelector(`#${CONTAINER_ID} .screen`)) {
|
||||
if (!this.ready && this._container.querySelector(".screen")) {
|
||||
// Once the screen element is added to the DOM, wait for the
|
||||
// animation frame after next to ensure that _positionCallout
|
||||
// has access to the rendered screen with the correct height
|
||||
|
@ -973,9 +970,7 @@ export class FeatureCallout {
|
|||
);
|
||||
this.win.addEventListener("keypress", this, { capture: true });
|
||||
this._positionCallout();
|
||||
let button = this.doc
|
||||
.getElementById(CONTAINER_ID)
|
||||
.querySelector(".primary");
|
||||
let button = this._container.querySelector(".primary");
|
||||
button.focus();
|
||||
this.win.addEventListener("focus", this, {
|
||||
capture: true, // get the event before retargeting
|
||||
|
@ -988,8 +983,7 @@ export class FeatureCallout {
|
|||
|
||||
this._pageEventManager?.clear();
|
||||
this.ready = false;
|
||||
const container = this.doc.getElementById(CONTAINER_ID);
|
||||
container?.remove();
|
||||
this._container?.remove();
|
||||
|
||||
// If user has disabled CFR, don't show any callouts. But make sure we load
|
||||
// the necessary stylesheets first, since re-enabling CFR should allow
|
||||
|
@ -1049,16 +1043,15 @@ export class FeatureCallout {
|
|||
* custom properties in inline styles. These custom properties are consumed by
|
||||
* _feature-callout-theme.scss, which is bundled with the other styles that
|
||||
* are loaded by {@link FeatureCallout.prototype._addCalloutLinkElements}.
|
||||
* @param {Element} [container] Root element of the feature callout
|
||||
*/
|
||||
_applyTheme(container = this.doc?.getElementById(CONTAINER_ID)) {
|
||||
if (container) {
|
||||
_applyTheme() {
|
||||
if (this._container) {
|
||||
// This tells the stylesheets to use -moz-content-prefers-color-scheme
|
||||
// instead of prefers-color-scheme, in order to follow the content color
|
||||
// scheme instead of the chrome color scheme, in case of a mismatch when
|
||||
// the feature callout exists in the chrome but is meant to look like it's
|
||||
// part of the content of a page in a browser tab (like PDF.js).
|
||||
container.classList.toggle(
|
||||
this._container.classList.toggle(
|
||||
"simulateContent",
|
||||
this.page === "chrome" && this.theme.simulateContent
|
||||
);
|
||||
|
@ -1066,7 +1059,6 @@ export class FeatureCallout {
|
|||
const scheme = this.theme[type];
|
||||
for (const name of FeatureCallout.themePropNames) {
|
||||
this._setThemeVariable(
|
||||
container,
|
||||
`--fc-${name}-${type}`,
|
||||
scheme?.[name] || this.theme.all[name]
|
||||
);
|
||||
|
@ -1077,15 +1069,14 @@ export class FeatureCallout {
|
|||
|
||||
/**
|
||||
* Set or remove a CSS custom property on the feature callout container
|
||||
* @param {Element} container Root element of the feature callout
|
||||
* @param {String} name Name of the CSS custom property
|
||||
* @param {String|void} [value] Value of the property, or omit to remove it
|
||||
*/
|
||||
_setThemeVariable(container, name, value) {
|
||||
_setThemeVariable(name, value) {
|
||||
if (value) {
|
||||
container.style.setProperty(name, value);
|
||||
this._container.style.setProperty(name, value);
|
||||
} else {
|
||||
container.style.removeProperty(name);
|
||||
this._container.style.removeProperty(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ add_task(async function test_CLICK_ELEMENT() {
|
|||
|
||||
await withFirefoxView({ openNewWindow: true }, async browser => {
|
||||
const { document } = browser.contentWindow;
|
||||
const calloutSelector = "#root.featureCallout";
|
||||
const calloutSelector = "#multi-stage-message-root.featureCallout";
|
||||
|
||||
await BrowserTestUtils.waitForCondition(() => {
|
||||
return document.querySelector(
|
||||
|
|
Загрузка…
Ссылка в новой задаче