зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1740377 - Update More From Mozilla section inside about:preferences to use new UI template r=preferences-reviewers,Gijs
Differential Revision: https://phabricator.services.mozilla.com/D131560
This commit is contained in:
Родитель
12d3098eb4
Коммит
00d26b7582
|
@ -14,13 +14,16 @@ category-more-from-mozilla =
|
|||
pane-more-from-mozilla-subtitle = Check out other Mozilla products that work to support a healthy internet.
|
||||
|
||||
firefox-mobile-title = { -brand-product-name } Mobile
|
||||
firefox-mobile-description = Get the mobile browser that puts your privacy first.
|
||||
firefox-mobile-description = The mobile browser that puts your privacy first.
|
||||
more-mozilla-advanced-firefox-mobile-description = From blocking trackers to putting the brakes on autoplay annoyances, Firefox mobile browsers work overtime to make sure you’re getting the good Internet.
|
||||
|
||||
mozilla-vpn-title = { -mozilla-vpn-brand-name }
|
||||
mozilla-vpn-description = Discover an added layer of anonymous browsing and protection.
|
||||
more-mozilla-advanced-mozilla-vpn-description = Mozilla VPN adds another layer of anonymous browsing and protection. And, unlike some other VPNs, it’s secure and doesn’t track your activity.
|
||||
|
||||
mozilla-rally-title = { -vendor-short-name } Rally
|
||||
mozilla-rally-description = Put your data to work for a better Internet for everyone.
|
||||
more-mozilla-advanced-mozilla-rally-description = Donate your data to research studies working to create a safer, more open Internet that helps people, not Big Tech.
|
||||
|
||||
button-firefox-mobile =
|
||||
.label = Get { -brand-product-name } Mobile
|
||||
|
@ -30,3 +33,5 @@ button-mozilla-vpn =
|
|||
|
||||
button-mozilla-rally =
|
||||
.label = Join Rally
|
||||
|
||||
more-mozilla-learn-more-link = Learn more
|
||||
|
|
|
@ -13,33 +13,40 @@
|
|||
data-category="paneMoreFromMozilla">
|
||||
<html:h1 class="title" data-l10n-id="pane-more-from-mozilla-title" />
|
||||
<html:p class="subtitle" data-l10n-id="pane-more-from-mozilla-subtitle" />
|
||||
<!-- Mozilla Products -->
|
||||
<vbox class="list-item">
|
||||
<label>
|
||||
<html:h2 id="firefox-mobile" class="product-title" data-l10n-id="firefox-mobile-title" />
|
||||
</label>
|
||||
<html:p class="description" data-l10n-id="firefox-mobile-description" />
|
||||
<hbox>
|
||||
<button id="fxMobile" class="primary small-button" data-l10n-id="button-firefox-mobile" />
|
||||
</hbox>
|
||||
</vbox>
|
||||
<vbox class="list-item">
|
||||
<label>
|
||||
<html:h2 id="mozilla-vpn" class="product-title" data-l10n-id="mozilla-vpn-title" />
|
||||
</label>
|
||||
<html:p class="description" data-l10n-id="mozilla-vpn-description" />
|
||||
<hbox>
|
||||
<button id="mozillaVPN" class="primary small-button" data-l10n-id="button-mozilla-vpn" />
|
||||
</hbox>
|
||||
</vbox>
|
||||
<vbox class="list-item">
|
||||
<label>
|
||||
<html:h2 id="mozilla-rally" class="product-title" data-l10n-id="mozilla-rally-title" />
|
||||
</label>
|
||||
<html:p class="description" data-l10n-id="mozilla-rally-description" />
|
||||
<hbox>
|
||||
<button id="mozillaRally" class="primary small-button" data-l10n-id="button-mozilla-rally" />
|
||||
</hbox>
|
||||
</vbox>
|
||||
</vbox>
|
||||
</html:template>
|
||||
<html:template id="simple">
|
||||
<vbox class="list-item simple">
|
||||
<hbox>
|
||||
<label>
|
||||
<html:h2 class="product-title" />
|
||||
</label>
|
||||
</hbox>
|
||||
<hbox>
|
||||
<html:p class="description" />
|
||||
<html:a class="text-link wants-telemetry" hidden="true" />
|
||||
</hbox>
|
||||
<hbox>
|
||||
<button class="primary small-button" hidden="true" />
|
||||
</hbox>
|
||||
<hbox>
|
||||
<html:div class="qrcode-section" hidden="true" />
|
||||
</hbox>
|
||||
</vbox>
|
||||
</html:template>
|
||||
|
||||
<html:template id="advanced">
|
||||
<vbox class="list-item advanced">
|
||||
<hbox class="product-img">
|
||||
<vbox class="product-info" flex="1">
|
||||
<label>
|
||||
<html:h2 class="product-title" />
|
||||
</label>
|
||||
<html:p class="description" />
|
||||
<html:a class="text-link wants-telemetry" hidden="true" />
|
||||
<html:div><button class="primary small-button" hidden="true"/></html:div>
|
||||
</vbox>
|
||||
<html:div class="qrcode-section" hidden="true" />
|
||||
</hbox>
|
||||
</vbox>
|
||||
</html:template>
|
||||
|
|
|
@ -6,23 +6,135 @@
|
|||
|
||||
var gMoreFromMozillaPane = {
|
||||
initialized: false,
|
||||
option: null,
|
||||
|
||||
openURL(url) {
|
||||
getURL(url, option) {
|
||||
const URL_PARAMS = {
|
||||
utm_source: "about-preferences",
|
||||
utm_campaign: "morefrommozilla-na",
|
||||
utm_medium: "firefox-release-browser",
|
||||
entrypoint_experiment: "morefrommozilla",
|
||||
entrypoint_variation: "a",
|
||||
utm_source: "about-prefs",
|
||||
utm_campaign: "morefrommozilla",
|
||||
utm_medium: "firefox-desktop",
|
||||
};
|
||||
// UTM content param used in analytics to record
|
||||
// UI template used to open URL
|
||||
const utm_content = {
|
||||
simple: "fxvt-113-a-na",
|
||||
advanced: "fxvt-113-b-na",
|
||||
};
|
||||
|
||||
let pageUrl = new URL(url);
|
||||
for (let [key, val] of Object.entries(URL_PARAMS)) {
|
||||
pageUrl.searchParams.append(key, val);
|
||||
}
|
||||
if (option) {
|
||||
pageUrl.searchParams.set("utm_content", utm_content[option]);
|
||||
}
|
||||
return pageUrl.toString();
|
||||
},
|
||||
|
||||
renderProducts() {
|
||||
let products = [
|
||||
{
|
||||
id: "firefox-mobile",
|
||||
title_string_id: "firefox-mobile-title",
|
||||
description_string_id: "firefox-mobile-description",
|
||||
qrcode: null,
|
||||
button: {
|
||||
id: "fxMobile",
|
||||
type: "link",
|
||||
label_string_id: "more-mozilla-learn-more-link",
|
||||
actionURL: "https://www.mozilla.org/firefox/browsers/mobile/",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "mozilla-vpn",
|
||||
title_string_id: "mozilla-vpn-title",
|
||||
description_string_id: "mozilla-vpn-description",
|
||||
button: {
|
||||
id: "mozillaVPN",
|
||||
label_string_id: "button-mozilla-vpn",
|
||||
actionURL: "https://www.mozilla.org/products/vpn/",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "mozilla-rally",
|
||||
title_string_id: "mozilla-rally-title",
|
||||
description_string_id: "mozilla-rally-description",
|
||||
button: {
|
||||
id: "mozillaRally",
|
||||
label_string_id: "button-mozilla-rally",
|
||||
actionURL: "https://rally.mozilla.org/",
|
||||
},
|
||||
},
|
||||
];
|
||||
this._productsContainer = document.getElementById(
|
||||
"moreFromMozillaCategory"
|
||||
);
|
||||
let frag = document.createDocumentFragment();
|
||||
this._template = document.getElementById(this.option || "simple");
|
||||
|
||||
// Exit when template is not found
|
||||
if (!this._template) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (let product of products) {
|
||||
let template = this._template.content.cloneNode(true);
|
||||
let title = template.querySelector(".product-title");
|
||||
let desc = template.querySelector(".description");
|
||||
|
||||
title.setAttribute("data-l10n-id", product.title_string_id);
|
||||
title.id = product.id;
|
||||
|
||||
// Handle advanced template display of product details
|
||||
if (this.option === "advanced") {
|
||||
template.querySelector(".product-img").id = `${product.id}-image`;
|
||||
desc.setAttribute(
|
||||
"data-l10n-id",
|
||||
`more-mozilla-advanced-${product.description_string_id}`
|
||||
);
|
||||
} else {
|
||||
desc.setAttribute("data-l10n-id", product.description_string_id);
|
||||
}
|
||||
|
||||
let isLink = product.button.type === "link";
|
||||
let actionElement = template.querySelector(
|
||||
isLink ? ".text-link" : ".small-button"
|
||||
);
|
||||
|
||||
if (actionElement) {
|
||||
actionElement.hidden = false;
|
||||
actionElement.id = `${this.option}-${product.button.id}`;
|
||||
actionElement.setAttribute(
|
||||
"data-l10n-id",
|
||||
product.button.label_string_id
|
||||
);
|
||||
|
||||
if (isLink) {
|
||||
actionElement.setAttribute(
|
||||
"href",
|
||||
this.getURL(product.button.actionURL, this.option)
|
||||
);
|
||||
actionElement.setAttribute("target", "_blank");
|
||||
} else {
|
||||
actionElement.addEventListener("click", function() {
|
||||
let mainWindow = window.windowRoot.ownerGlobal;
|
||||
mainWindow.openTrustedLinkIn(pageUrl.toString(), "tab");
|
||||
mainWindow.openTrustedLinkIn(
|
||||
gMoreFromMozillaPane.getURL(
|
||||
product.button.actionURL,
|
||||
gMoreFromMozillaPane.option
|
||||
),
|
||||
"tab"
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (product.qrcode) {
|
||||
template.querySelector(".qrcode-section").hidden = false;
|
||||
}
|
||||
frag.appendChild(template);
|
||||
}
|
||||
this._productsContainer.appendChild(frag);
|
||||
},
|
||||
|
||||
async init() {
|
||||
|
@ -34,20 +146,6 @@ var gMoreFromMozillaPane = {
|
|||
.getElementById("moreFromMozillaCategory")
|
||||
.removeAttribute("data-hidden-from-search");
|
||||
|
||||
document.getElementById("mozillaVPN").addEventListener("click", function() {
|
||||
gMoreFromMozillaPane.openURL("https://www.mozilla.org/products/vpn/");
|
||||
});
|
||||
|
||||
document.getElementById("fxMobile").addEventListener("click", function() {
|
||||
gMoreFromMozillaPane.openURL(
|
||||
"https://www.mozilla.org/en-US/firefox/browsers/mobile/"
|
||||
);
|
||||
});
|
||||
|
||||
document
|
||||
.getElementById("mozillaRally")
|
||||
.addEventListener("click", function() {
|
||||
gMoreFromMozillaPane.openURL("https://rally.mozilla.org/");
|
||||
});
|
||||
this.renderProducts();
|
||||
},
|
||||
};
|
||||
|
|
|
@ -205,6 +205,9 @@ function init_all() {
|
|||
NimbusFeatures.moreFromMozilla.recordExposureEvent({ once: true });
|
||||
if (NimbusFeatures.moreFromMozilla.getVariable("enabled")) {
|
||||
document.getElementById("category-more-from-mozilla").hidden = false;
|
||||
gMoreFromMozillaPane.option = NimbusFeatures.moreFromMozilla.getVariable(
|
||||
"template"
|
||||
);
|
||||
register_module("paneMoreFromMozilla", gMoreFromMozillaPane);
|
||||
}
|
||||
// The Sync category needs to be the last of the "real" categories
|
||||
|
|
|
@ -88,3 +88,68 @@ add_task(async function test_aboutpreferences_event_telemetry() {
|
|||
TelemetryTestUtils.assertNumberOfEvents(2);
|
||||
BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
});
|
||||
|
||||
add_task(async function test_aboutpreferences_simple_template() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
["browser.preferences.moreFromMozilla", true],
|
||||
["browser.preferences.moreFromMozilla.template", "simple"],
|
||||
],
|
||||
});
|
||||
await openPreferencesViaOpenPreferencesAPI("paneGeneral", {
|
||||
leaveOpen: true,
|
||||
});
|
||||
|
||||
let doc = gBrowser.contentDocument;
|
||||
let moreFromMozillaCategory = doc.getElementById(
|
||||
"category-more-from-mozilla"
|
||||
);
|
||||
|
||||
let clickedPromise = ContentTaskUtils.waitForEvent(
|
||||
moreFromMozillaCategory,
|
||||
"click"
|
||||
);
|
||||
moreFromMozillaCategory.click();
|
||||
await clickedPromise;
|
||||
|
||||
let productCards = doc.querySelectorAll("vbox.simple");
|
||||
Assert.ok(productCards, "The product cards from simple template found");
|
||||
Assert.equal(productCards.length, 3, "3 product cards displayed");
|
||||
BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
});
|
||||
|
||||
add_task(async function test_aboutpreferences_advanced_template() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
["browser.preferences.moreFromMozilla", true],
|
||||
["browser.preferences.moreFromMozilla.template", "advanced"],
|
||||
],
|
||||
});
|
||||
await openPreferencesViaOpenPreferencesAPI("paneGeneral", {
|
||||
leaveOpen: true,
|
||||
});
|
||||
|
||||
let doc = gBrowser.contentDocument;
|
||||
let moreFromMozillaCategory = doc.getElementById(
|
||||
"category-more-from-mozilla"
|
||||
);
|
||||
|
||||
let clickedPromise = ContentTaskUtils.waitForEvent(
|
||||
moreFromMozillaCategory,
|
||||
"click"
|
||||
);
|
||||
moreFromMozillaCategory.click();
|
||||
await clickedPromise;
|
||||
|
||||
let productCards = doc.querySelectorAll("vbox.advanced");
|
||||
Assert.ok(productCards, "The product cards from advanced template found");
|
||||
Assert.equal(productCards.length, 3, "3 product cards displayed");
|
||||
Assert.deepEqual(
|
||||
Array.from(productCards).map(
|
||||
node => node.querySelector(".product-img")?.id
|
||||
),
|
||||
["firefox-mobile-image", "mozilla-vpn-image", "mozilla-rally-image"],
|
||||
"Advanced template product marketing images"
|
||||
);
|
||||
BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
});
|
||||
|
|
|
@ -814,7 +814,10 @@ let BrowserUsageTelemetry = {
|
|||
|
||||
// Find the actual element we're interested in.
|
||||
let node = sourceEvent.target;
|
||||
while (!UI_TARGET_ELEMENTS.includes(node.localName)) {
|
||||
while (
|
||||
!UI_TARGET_ELEMENTS.includes(node.localName) &&
|
||||
!node.classList?.contains("wants-telemetry")
|
||||
) {
|
||||
node = node.parentNode;
|
||||
if (!node) {
|
||||
// A click on a space or label or something we're not interested in.
|
||||
|
|
|
@ -85,6 +85,9 @@
|
|||
skin/classic/browser/preferences/face-smile.svg (../shared/preferences/face-smile.svg)
|
||||
skin/classic/browser/preferences/fxaPairDevice.css (../shared/preferences/fxaPairDevice.css)
|
||||
skin/classic/browser/preferences/ios-menu.svg (../shared/preferences/ios-menu.svg)
|
||||
skin/classic/browser/preferences/img-mobile.svg (../shared/preferences/img-mobile.svg)
|
||||
skin/classic/browser/preferences/img-rally.png (../shared/preferences/img-rally.png)
|
||||
skin/classic/browser/preferences/img-vpn.svg (../shared/preferences/img-vpn.svg)
|
||||
skin/classic/browser/preferences/mozilla-logo.svg (../shared/preferences/mozilla-logo.svg)
|
||||
skin/classic/browser/preferences/no-search-bar.svg (../shared/preferences/no-search-bar.svg)
|
||||
skin/classic/browser/preferences/privacy.css (../shared/preferences/privacy.css)
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
После Ширина: | Высота: | Размер: 12 KiB |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 34 KiB |
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
После Ширина: | Высота: | Размер: 11 KiB |
|
@ -1186,15 +1186,28 @@ richlistitem .text-link:hover {
|
|||
}
|
||||
|
||||
#moreFromMozillaCategory .product-title {
|
||||
margin: 4px 0;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
padding-inline-start: 30px;
|
||||
margin: 4px 0;
|
||||
-moz-context-properties: fill;
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
#moreFromMozillaCategory .product-title:-moz-locale-dir(rtl) {
|
||||
#moreFromMozillaCategory .advanced .product-title {
|
||||
background-size: initial;
|
||||
padding-inline-start: 0;
|
||||
padding-top: 33px;
|
||||
}
|
||||
|
||||
#moreFromMozillaCategory .product-img {
|
||||
background-repeat: no-repeat;
|
||||
background-size: 150px;
|
||||
padding-inline-start: 174px;
|
||||
}
|
||||
|
||||
#moreFromMozillaCategory .product-title:-moz-locale-dir(rtl),
|
||||
#moreFromMozillaCategory .product-img:-moz-locale-dir(rtl) {
|
||||
background-position-x: right;
|
||||
}
|
||||
|
||||
|
@ -1204,13 +1217,46 @@ richlistitem .text-link:hover {
|
|||
margin: 4px 0;
|
||||
}
|
||||
|
||||
#moreFromMozillaCategory button {
|
||||
#moreFromMozillaCategory .advanced .description {
|
||||
padding-inline-start: 0;
|
||||
}
|
||||
|
||||
#moreFromMozillaCategory .small-button {
|
||||
margin-block: 16px;
|
||||
margin-inline: 30px 0;
|
||||
}
|
||||
|
||||
#moreFromMozillaCategory .advanced .small-button {
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
#moreFromMozillaCategory vbox.advanced {
|
||||
box-shadow: 0 2px 6px rgba(58, 57, 68, 0.2);
|
||||
border-radius: 4px;
|
||||
margin-block: 20px 10px;
|
||||
margin-inline: 2px 0;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
#moreFromMozillaCategory vbox.advanced {
|
||||
background-color: rgb(66, 65, 77);
|
||||
}
|
||||
}
|
||||
|
||||
#moreFromMozillaCategory .advanced .product-info {
|
||||
min-height: 200px;
|
||||
}
|
||||
|
||||
#moreFromMozillaCategory .simple .text-link {
|
||||
display: block;
|
||||
margin-block: 4px 0;
|
||||
margin-inline-start: 4px;
|
||||
}
|
||||
|
||||
#firefox-mobile {
|
||||
background-image: url("chrome://branding/content/about-logo.svg");
|
||||
background-image: url("chrome://devtools/skin/images/browsers/mobile.svg");
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
#mozilla-vpn {
|
||||
|
@ -1220,3 +1266,15 @@ richlistitem .text-link:hover {
|
|||
#mozilla-rally {
|
||||
background-image: url("chrome://browser/skin/preferences/rally-logo.svg");
|
||||
}
|
||||
|
||||
#firefox-mobile-image {
|
||||
background-image: url("chrome://browser/skin/preferences/img-mobile.svg");
|
||||
}
|
||||
|
||||
#mozilla-vpn-image {
|
||||
background-image: url("chrome://browser/skin/preferences/img-vpn.svg");
|
||||
}
|
||||
|
||||
#mozilla-rally-image {
|
||||
background-image: url("chrome://browser/skin/preferences/img-rally.png");
|
||||
}
|
||||
|
|
|
@ -112,6 +112,10 @@ moreFromMozilla:
|
|||
type: boolean
|
||||
fallbackPref: browser.preferences.moreFromMozilla
|
||||
description: Should users see the new more from Mozilla section.
|
||||
template:
|
||||
type: string
|
||||
fallbackPref: browser.preferences.moreFromMozilla.template
|
||||
description: UI template used to display Mozilla products. Possible values simple, advanced. Default is simple.
|
||||
abouthomecache:
|
||||
description: "The startup about:home cache."
|
||||
hasExposure: false
|
||||
|
|
Загрузка…
Ссылка в новой задаче