forked from mirrors/gecko-dev
166 lines
5.1 KiB
JavaScript
166 lines
5.1 KiB
JavaScript
/* 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 browser = window.docShell.chromeEventHandler;
|
|
const { document: gDoc, XPCOMUtils } = browser.ownerGlobal;
|
|
|
|
XPCOMUtils.defineLazyModuleGetters(this, {
|
|
AboutWelcomeParent: "resource:///actors/AboutWelcomeParent.jsm",
|
|
RemoteL10n: "resource://activity-stream/lib/RemoteL10n.jsm",
|
|
});
|
|
|
|
const [CONFIG, PARAMS] = window.arguments[0];
|
|
|
|
function cloneTemplate(id) {
|
|
return document.getElementById(id).content.cloneNode(true);
|
|
}
|
|
|
|
function addStylesheet(href) {
|
|
const link = document.head.appendChild(document.createElement("link"));
|
|
link.rel = "stylesheet";
|
|
link.href = href;
|
|
}
|
|
|
|
/**
|
|
* Render content based on Spotlight-specific templates.
|
|
*/
|
|
async function renderSpotlight(ready) {
|
|
const { template, logo = {}, body, extra = {} } = CONFIG;
|
|
|
|
// Add Spotlight styles
|
|
addStylesheet("chrome://browser/skin/spotlight.css");
|
|
|
|
// Apply desired message template.
|
|
const clone = cloneTemplate(template);
|
|
document.body.classList.add(template);
|
|
|
|
// Render logo element.
|
|
let imageEl = clone.querySelector(".logo");
|
|
imageEl.src = logo.imageURL;
|
|
imageEl.style.height = imageEl.style.width = logo.size;
|
|
|
|
// Set text data of an element by class name with local/remote as configured.
|
|
const setText = (className, config) => {
|
|
const el = clone.querySelector(`.${className}`);
|
|
if (!config.label) {
|
|
el.remove();
|
|
return;
|
|
}
|
|
|
|
el.appendChild(
|
|
RemoteL10n.createElement(document, "span", { content: config.label })
|
|
);
|
|
el.style.fontSize = config.size;
|
|
};
|
|
|
|
// Render main body text elements.
|
|
Object.entries(body).forEach(entry => setText(...entry));
|
|
|
|
// Optionally apply and render extra behaviors.
|
|
const { expanded } = extra;
|
|
if (expanded) {
|
|
// Add the expanded behavior to the main text content.
|
|
clone
|
|
.querySelector("#content")
|
|
.append(cloneTemplate("extra-content-expanded"));
|
|
setText("expanded", expanded);
|
|
|
|
// Initialize state and handle toggle events.
|
|
const toggleBtn = clone.querySelector("#learn-more-toggle");
|
|
const toggle = () => {
|
|
const toExpand = !!toggleBtn.dataset.l10nId?.includes("collapsed");
|
|
document.l10n.setAttributes(
|
|
toggleBtn,
|
|
toExpand
|
|
? "spotlight-learn-more-expanded"
|
|
: "spotlight-learn-more-collapsed"
|
|
);
|
|
toggleBtn.setAttribute("aria-expanded", toExpand);
|
|
};
|
|
toggleBtn.addEventListener("click", toggle);
|
|
toggle();
|
|
}
|
|
|
|
document.body.appendChild(clone);
|
|
|
|
let primaryBtn = document.getElementById("primary");
|
|
let secondaryBtn = document.getElementById("secondary");
|
|
if (primaryBtn) {
|
|
primaryBtn.addEventListener("click", () => {
|
|
PARAMS.primaryBtn = true;
|
|
window.close();
|
|
});
|
|
|
|
// If we just call focus() at some random time, it'll cause a flush,
|
|
// which slows things down unnecessarily, so instead we use rAF...
|
|
requestAnimationFrame(() => {
|
|
primaryBtn.focus({ preventFocusRing: true });
|
|
});
|
|
}
|
|
if (secondaryBtn) {
|
|
secondaryBtn.addEventListener("click", () => {
|
|
PARAMS.secondaryBtn = true;
|
|
window.close();
|
|
});
|
|
}
|
|
|
|
// Wait for translations to load before getting sizing information.
|
|
await document.l10n.ready;
|
|
await document.l10n.translateElements(clone.children);
|
|
requestAnimationFrame(() => requestAnimationFrame(ready));
|
|
}
|
|
|
|
/**
|
|
* Render content based on about:welcome multistage template.
|
|
*/
|
|
function renderMultistage(ready) {
|
|
const AWParent = new AboutWelcomeParent();
|
|
const receive = name => data =>
|
|
AWParent.onContentMessage(`AWPage:${name}`, data, browser);
|
|
|
|
// Expose top level functions expected by the bundle.
|
|
window.AWGetDefaultSites = () => {};
|
|
window.AWGetFeatureConfig = () => CONFIG;
|
|
window.AWGetFxAMetricsFlowURI = () => {};
|
|
window.AWGetImportableSites = () => "[]";
|
|
window.AWGetRegion = receive("GET_REGION");
|
|
window.AWGetSelectedTheme = receive("GET_SELECTED_THEME");
|
|
window.AWSendEventTelemetry = receive("TELEMETRY_EVENT");
|
|
window.AWSendToParent = (name, data) => receive(name)(data);
|
|
window.AWFinish = () => {
|
|
window.close();
|
|
};
|
|
|
|
// Update styling to be compatible with about:welcome.
|
|
addStylesheet(
|
|
"chrome://activity-stream/content/aboutwelcome/aboutwelcome.css"
|
|
);
|
|
|
|
document.body.classList.add("onboardingContainer");
|
|
document.body.id = "root";
|
|
|
|
// The content handles styling including its own modal shadowing.
|
|
const { classList } = gDoc.getElementById("window-modal-dialog");
|
|
classList.add("noShadow");
|
|
addEventListener("pagehide", () => classList.remove("noShadow"));
|
|
|
|
// Load the bundle to render the content as configured.
|
|
document.head.appendChild(document.createElement("script")).src =
|
|
"resource://activity-stream/aboutwelcome/aboutwelcome.bundle.js";
|
|
ready();
|
|
}
|
|
|
|
// Indicate when we're ready to show and size (async localized) content.
|
|
document.mozSubdialogReady = new Promise(resolve =>
|
|
document.addEventListener(
|
|
"DOMContentLoaded",
|
|
() =>
|
|
(CONFIG.template === "multistage" ? renderMultistage : renderSpotlight)(
|
|
resolve
|
|
),
|
|
{
|
|
once: true,
|
|
}
|
|
)
|
|
);
|