зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1357641 - Part 1: Add onboarding tour notification, r=flod,mossop
This commit - adds onboarding tour notification - shows still not completed onboarding tour notifications in order - opens target tour from tour notification for the target tour MozReview-Commit-ID: AwLtwjoeARQ --HG-- extra : rebase_source : 264531cf8aaf3f636faecf790a269d0166188f8a
This commit is contained in:
Родитель
84434ba58f
Коммит
085aa9b471
|
@ -11,7 +11,8 @@ Cu.import("resource://gre/modules/Preferences.jsm");
|
||||||
const PREF_WHITELIST = [
|
const PREF_WHITELIST = [
|
||||||
"browser.onboarding.enabled",
|
"browser.onboarding.enabled",
|
||||||
"browser.onboarding.hidden",
|
"browser.onboarding.hidden",
|
||||||
"browser.onboarding.notification.finished"
|
"browser.onboarding.notification.finished",
|
||||||
|
"browser.onboarding.notification.lastPrompted"
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -37,7 +37,8 @@
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#onboarding-overlay-close-btn {
|
#onboarding-overlay-close-btn,
|
||||||
|
#onboarding-notification-close-btn {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 15px;
|
top: 15px;
|
||||||
offset-inline-end: 15px;
|
offset-inline-end: 15px;
|
||||||
|
@ -50,7 +51,8 @@
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#onboarding-overlay-close-btn:hover {
|
#onboarding-overlay-close-btn:hover,
|
||||||
|
#onboarding-notification-close-btn:hover {
|
||||||
background-color: rgba(204, 204, 204, 0.6);
|
background-color: rgba(204, 204, 204, 0.6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,7 +238,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
#onboarding-tour-search.onboarding-active,
|
#onboarding-tour-search.onboarding-active,
|
||||||
#onboarding-tour-search:hover {
|
#onboarding-tour-search:hover,
|
||||||
|
#onboarding-notification-bar[data-target-tour-id=onboarding-tour-search] #onboarding-notification-tour-icon {
|
||||||
background-image: url("img/icons_search-colored.svg");
|
background-image: url("img/icons_search-colored.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,7 +248,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
#onboarding-tour-private-browsing.onboarding-active,
|
#onboarding-tour-private-browsing.onboarding-active,
|
||||||
#onboarding-tour-private-browsing:hover {
|
#onboarding-tour-private-browsing:hover,
|
||||||
|
#onboarding-notification-bar[data-target-tour-id=onboarding-tour-private-browsing] #onboarding-notification-tour-icon {
|
||||||
background-image: url("img/icons_private-colored.svg");
|
background-image: url("img/icons_private-colored.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,7 +258,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
#onboarding-tour-addons.onboarding-active,
|
#onboarding-tour-addons.onboarding-active,
|
||||||
#onboarding-tour-addons:hover {
|
#onboarding-tour-addons:hover,
|
||||||
|
#onboarding-notification-bar[data-target-tour-id=onboarding-tour-addons] #onboarding-notification-tour-icon {
|
||||||
background-image: url("img/icons_addons-colored.svg");
|
background-image: url("img/icons_addons-colored.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,7 +268,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
#onboarding-tour-customize.onboarding-active,
|
#onboarding-tour-customize.onboarding-active,
|
||||||
#onboarding-tour-customize:hover {
|
#onboarding-tour-customize:hover,
|
||||||
|
#onboarding-notification-bar[data-target-tour-id=onboarding-tour-customize] #onboarding-notification-tour-icon {
|
||||||
background-image: url("img/icons_customize-colored.svg");
|
background-image: url("img/icons_customize-colored.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,6 +278,105 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
#onboarding-tour-default-browser.onboarding-active,
|
#onboarding-tour-default-browser.onboarding-active,
|
||||||
#onboarding-tour-default-browser:hover {
|
#onboarding-tour-default-browser:hover,
|
||||||
|
#onboarding-notification-bar[data-target-tour-id=onboarding-tour-default-browser] #onboarding-notification-tour-icon {
|
||||||
background-image: url("img/icons_default-colored.svg");
|
background-image: url("img/icons_default-colored.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Tour Notifications */
|
||||||
|
#onboarding-notification-bar {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 998; /* We want this always under #onboarding-overlay */
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 122px;
|
||||||
|
min-width: 1060px;
|
||||||
|
background: rgba(255, 255, 255, 0.97);
|
||||||
|
border-top: 2px solid #e9e9e9;
|
||||||
|
transition: transform 0.8s;
|
||||||
|
transform: translateY(122px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#onboarding-notification-bar.onboarding-opened {
|
||||||
|
transform: translateY(0px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#onboarding-notification-icon {
|
||||||
|
height: 36px;
|
||||||
|
background: url("img/overlay-icon.svg") no-repeat;
|
||||||
|
background-size: 36px;
|
||||||
|
background-position: 34px;
|
||||||
|
padding-inline-start: 190px;
|
||||||
|
position: absolute;
|
||||||
|
offset-block-start: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
#onboarding-notification-icon::after {
|
||||||
|
--height: 22px;
|
||||||
|
content: attr(data-tooltip);
|
||||||
|
background: #5ce6e6;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
offset-inline-start: 68px;
|
||||||
|
color: #10404a;
|
||||||
|
font-size: 12px;
|
||||||
|
min-height: var(--height);
|
||||||
|
line-height: var(--height);
|
||||||
|
border-radius: calc(var(--height) / 2);
|
||||||
|
border: 1px solid #fff;
|
||||||
|
padding: 0 10px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#onboarding-notification-close-btn {
|
||||||
|
background-color: rgba(255, 255, 255, 0.97);
|
||||||
|
border: none;
|
||||||
|
position: absolute;
|
||||||
|
offset-block-start: 50%;
|
||||||
|
offset-inline-end: 34px;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
#onboarding-notification-message-section {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
position: absolute;
|
||||||
|
offset-block-start: 50%;
|
||||||
|
offset-inline-start: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
#onboarding-notification-body {
|
||||||
|
width: 420px;
|
||||||
|
margin: 0 15px;
|
||||||
|
color: #0c0c0d;;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#onboarding-notification-body * {
|
||||||
|
font-size: 13px
|
||||||
|
}
|
||||||
|
|
||||||
|
#onboarding-notification-tour-title {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#onboarding-notification-tour-icon {
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
#onboarding-notification-action-btn {
|
||||||
|
background: #0d96ff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 10px 20px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #fff;
|
||||||
|
box-shadow: 0 1px 0 rgba(0,0,0,0.23);
|
||||||
|
}
|
||||||
|
|
|
@ -27,6 +27,11 @@ const BRAND_SHORT_NAME = Services.strings
|
||||||
* id: "onboarding-tour-addons",
|
* id: "onboarding-tour-addons",
|
||||||
* // The string id of tour name which would be displayed on the navigation bar
|
* // The string id of tour name which would be displayed on the navigation bar
|
||||||
* tourNameId: "onboarding.tour-addon",
|
* tourNameId: "onboarding.tour-addon",
|
||||||
|
* // The method returing strings used on tour notification
|
||||||
|
* getNotificationStrings(bundle):
|
||||||
|
* - title: // The string of tour notification title
|
||||||
|
* - message: // The string of tour notification message
|
||||||
|
* - button: // The string of tour notification action button title
|
||||||
* // Return a div appended with elements for this tours.
|
* // Return a div appended with elements for this tours.
|
||||||
* // Each tour should contain the following 3 sections in the div:
|
* // Each tour should contain the following 3 sections in the div:
|
||||||
* // .onboarding-tour-description, .onboarding-tour-content, .onboarding-tour-button.
|
* // .onboarding-tour-description, .onboarding-tour-content, .onboarding-tour-button.
|
||||||
|
@ -39,6 +44,13 @@ var onboardingTours = [
|
||||||
{
|
{
|
||||||
id: "onboarding-tour-private-browsing",
|
id: "onboarding-tour-private-browsing",
|
||||||
tourNameId: "onboarding.tour-private-browsing",
|
tourNameId: "onboarding.tour-private-browsing",
|
||||||
|
getNotificationStrings(bundle) {
|
||||||
|
return {
|
||||||
|
title: bundle.GetStringFromName("onboarding.notification.onboarding-tour-private-browsing.title"),
|
||||||
|
message: bundle.GetStringFromName("onboarding.notification.onboarding-tour-private-browsing.message"),
|
||||||
|
button: bundle.GetStringFromName("onboarding.button.learnMore"),
|
||||||
|
};
|
||||||
|
},
|
||||||
getPage(win) {
|
getPage(win) {
|
||||||
let div = win.document.createElement("div");
|
let div = win.document.createElement("div");
|
||||||
div.innerHTML = `
|
div.innerHTML = `
|
||||||
|
@ -59,6 +71,13 @@ var onboardingTours = [
|
||||||
{
|
{
|
||||||
id: "onboarding-tour-addons",
|
id: "onboarding-tour-addons",
|
||||||
tourNameId: "onboarding.tour-addons",
|
tourNameId: "onboarding.tour-addons",
|
||||||
|
getNotificationStrings(bundle) {
|
||||||
|
return {
|
||||||
|
title: bundle.GetStringFromName("onboarding.notification.onboarding-tour-addons.title"),
|
||||||
|
message: bundle.formatStringFromName("onboarding.notification.onboarding-tour-addons.message", [BRAND_SHORT_NAME], 1),
|
||||||
|
button: bundle.GetStringFromName("onboarding.button.learnMore"),
|
||||||
|
};
|
||||||
|
},
|
||||||
getPage(win) {
|
getPage(win) {
|
||||||
let div = win.document.createElement("div");
|
let div = win.document.createElement("div");
|
||||||
div.innerHTML = `
|
div.innerHTML = `
|
||||||
|
@ -79,6 +98,13 @@ var onboardingTours = [
|
||||||
{
|
{
|
||||||
id: "onboarding-tour-customize",
|
id: "onboarding-tour-customize",
|
||||||
tourNameId: "onboarding.tour-customize",
|
tourNameId: "onboarding.tour-customize",
|
||||||
|
getNotificationStrings(bundle) {
|
||||||
|
return {
|
||||||
|
title: bundle.GetStringFromName("onboarding.notification.onboarding-tour-customize.title"),
|
||||||
|
message: bundle.formatStringFromName("onboarding.notification.onboarding-tour-customize.message", [BRAND_SHORT_NAME], 1),
|
||||||
|
button: bundle.GetStringFromName("onboarding.button.learnMore"),
|
||||||
|
};
|
||||||
|
},
|
||||||
getPage(win) {
|
getPage(win) {
|
||||||
let div = win.document.createElement("div");
|
let div = win.document.createElement("div");
|
||||||
div.innerHTML = `
|
div.innerHTML = `
|
||||||
|
@ -99,6 +125,13 @@ var onboardingTours = [
|
||||||
{
|
{
|
||||||
id: "onboarding-tour-search",
|
id: "onboarding-tour-search",
|
||||||
tourNameId: "onboarding.tour-search",
|
tourNameId: "onboarding.tour-search",
|
||||||
|
getNotificationStrings(bundle) {
|
||||||
|
return {
|
||||||
|
title: bundle.GetStringFromName("onboarding.notification.onboarding-tour-search.title"),
|
||||||
|
message: bundle.GetStringFromName("onboarding.notification.onboarding-tour-search.message"),
|
||||||
|
button: bundle.GetStringFromName("onboarding.button.learnMore"),
|
||||||
|
};
|
||||||
|
},
|
||||||
getPage(win) {
|
getPage(win) {
|
||||||
let div = win.document.createElement("div");
|
let div = win.document.createElement("div");
|
||||||
div.innerHTML = `
|
div.innerHTML = `
|
||||||
|
@ -119,6 +152,13 @@ var onboardingTours = [
|
||||||
{
|
{
|
||||||
id: "onboarding-tour-default-browser",
|
id: "onboarding-tour-default-browser",
|
||||||
tourNameId: "onboarding.tour-default-browser",
|
tourNameId: "onboarding.tour-default-browser",
|
||||||
|
getNotificationStrings(bundle) {
|
||||||
|
return {
|
||||||
|
title: bundle.formatStringFromName("onboarding.notification.onboarding-tour-default-browser.title", [BRAND_SHORT_NAME], 1),
|
||||||
|
message: bundle.formatStringFromName("onboarding.notification.onboarding-tour-default-browser.message", [BRAND_SHORT_NAME], 1),
|
||||||
|
button: bundle.GetStringFromName("onboarding.button.learnMore"),
|
||||||
|
};
|
||||||
|
},
|
||||||
getPage(win) {
|
getPage(win) {
|
||||||
let div = win.document.createElement("div");
|
let div = win.document.createElement("div");
|
||||||
let defaultBrowserButtonId = win.matchMedia("(-moz-os-version: windows-win7)").matches ?
|
let defaultBrowserButtonId = win.matchMedia("(-moz-os-version: windows-win7)").matches ?
|
||||||
|
@ -147,7 +187,6 @@ var onboardingTours = [
|
||||||
class Onboarding {
|
class Onboarding {
|
||||||
constructor(contentWindow) {
|
constructor(contentWindow) {
|
||||||
this.init(contentWindow);
|
this.init(contentWindow);
|
||||||
this._bundle = Services.strings.createBundle(BUNDLE_URI);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async init(contentWindow) {
|
async init(contentWindow) {
|
||||||
|
@ -157,6 +196,8 @@ class Onboarding {
|
||||||
// We want to create and append elements after CSS is loaded so
|
// We want to create and append elements after CSS is loaded so
|
||||||
// no flash of style changes and no additional reflow.
|
// no flash of style changes and no additional reflow.
|
||||||
await this._loadCSS();
|
await this._loadCSS();
|
||||||
|
this._bundle = Services.strings.createBundle(BUNDLE_URI);
|
||||||
|
|
||||||
this._overlayIcon = this._renderOverlayIcon();
|
this._overlayIcon = this._renderOverlayIcon();
|
||||||
this._overlay = this._renderOverlay();
|
this._overlay = this._renderOverlay();
|
||||||
this._window.document.body.appendChild(this._overlayIcon);
|
this._window.document.body.appendChild(this._overlayIcon);
|
||||||
|
@ -172,6 +213,25 @@ class Onboarding {
|
||||||
this._window.addEventListener("unload", () => this.destroy());
|
this._window.addEventListener("unload", () => this.destroy());
|
||||||
|
|
||||||
this._initPrefObserver();
|
this._initPrefObserver();
|
||||||
|
this._initNotification();
|
||||||
|
}
|
||||||
|
|
||||||
|
_initNotification() {
|
||||||
|
let doc = this._window.document;
|
||||||
|
if (doc.hidden) {
|
||||||
|
// When the preloaded-browser feature is on,
|
||||||
|
// it would preload an hidden about:newtab in the background.
|
||||||
|
// We don't wnat to show notification in that hidden state.
|
||||||
|
let onVisible = () => {
|
||||||
|
if (!doc.hidden) {
|
||||||
|
doc.removeEventListener("visibilitychange", onVisible);
|
||||||
|
this.showNotification();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
doc.addEventListener("visibilitychange", onVisible);
|
||||||
|
} else {
|
||||||
|
this.showNotification();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_initPrefObserver() {
|
_initPrefObserver() {
|
||||||
|
@ -219,6 +279,16 @@ class Onboarding {
|
||||||
case "onboarding-overlay":
|
case "onboarding-overlay":
|
||||||
this.toggleOverlay();
|
this.toggleOverlay();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "onboarding-notification-close-btn":
|
||||||
|
this.hideNotification();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "onboarding-notification-action-btn":
|
||||||
|
let tourId = this._notificationBar.dataset.targetTourId;
|
||||||
|
this.toggleOverlay();
|
||||||
|
this.gotoPage(tourId);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (evt.target.classList.contains("onboarding-tour-item")) {
|
if (evt.target.classList.contains("onboarding-tour-item")) {
|
||||||
this.gotoPage(evt.target.id);
|
this.gotoPage(evt.target.id);
|
||||||
|
@ -229,6 +299,9 @@ class Onboarding {
|
||||||
this._clearPrefObserver();
|
this._clearPrefObserver();
|
||||||
this._overlayIcon.remove();
|
this._overlayIcon.remove();
|
||||||
this._overlay.remove();
|
this._overlay.remove();
|
||||||
|
if (this._notificationBar) {
|
||||||
|
this._notificationBar.remove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleOverlay() {
|
toggleOverlay() {
|
||||||
|
@ -237,14 +310,13 @@ class Onboarding {
|
||||||
this._loadTours(onboardingTours);
|
this._loadTours(onboardingTours);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._overlay.classList.toggle("opened");
|
this.hideNotification();
|
||||||
|
this._overlay.classList.toggle("onboarding-opened");
|
||||||
|
|
||||||
let hiddenCheckbox = this._window.document.getElementById("onboarding-tour-hidden-checkbox");
|
let hiddenCheckbox = this._window.document.getElementById("onboarding-tour-hidden-checkbox");
|
||||||
if (hiddenCheckbox.checked) {
|
if (hiddenCheckbox.checked) {
|
||||||
this.hide();
|
this.hide();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this._overlay.classList.toggle("onboarding-opened");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gotoPage(tourId) {
|
gotoPage(tourId) {
|
||||||
|
@ -261,6 +333,108 @@ class Onboarding {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isTourCompleted(tourId) {
|
||||||
|
return Preferences.get(`browser.onboarding.tour.${tourId}.completed`, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
showNotification() {
|
||||||
|
if (Preferences.get("browser.onboarding.notification.finished", false)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pick out the next target tour to show
|
||||||
|
let targetTour = null;
|
||||||
|
|
||||||
|
// Take the last tour as the default last prompted
|
||||||
|
// so below would start from the 1st one if found no the last prompted from the pref.
|
||||||
|
let lastPromptedId = onboardingTours[onboardingTours.length - 1].id;
|
||||||
|
lastPromptedId = Preferences.get("browser.onboarding.notification.lastPrompted", lastPromptedId);
|
||||||
|
|
||||||
|
let lastTourIndex = onboardingTours.findIndex(tour => tour.id == lastPromptedId);
|
||||||
|
if (lastTourIndex < 0) {
|
||||||
|
// Couldn't find the tour.
|
||||||
|
// This could be because the pref was manually modified into unknown value
|
||||||
|
// or the tour version has been updated so have an new tours set.
|
||||||
|
// Take the last tour as the last prompted so would start from the 1st one below.
|
||||||
|
lastTourIndex = onboardingTours.length - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Form tours to notify into the order we want.
|
||||||
|
// For example, There are tour #0 ~ #5 and the #3 is the last prompted.
|
||||||
|
// This would form [#4, #5, #0, #1, #2, #3].
|
||||||
|
// So the 1st met incomplete tour in #4 ~ #2 would be the one to show.
|
||||||
|
// Or #3 would be the one to show if #4 ~ #2 are all completed.
|
||||||
|
let toursToNotify = [ ...onboardingTours.slice(lastTourIndex + 1), ...onboardingTours.slice(0, lastTourIndex + 1) ];
|
||||||
|
targetTour = toursToNotify.find(tour => !this.isTourCompleted(tour.id));
|
||||||
|
|
||||||
|
|
||||||
|
if (!targetTour) {
|
||||||
|
this.sendMessageToChrome("set-prefs", [{
|
||||||
|
name: "browser.onboarding.notification.finished",
|
||||||
|
value: true
|
||||||
|
}]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show the target tour notification
|
||||||
|
this._notificationBar = this._renderNotificationBar();
|
||||||
|
this._notificationBar.addEventListener("click", this);
|
||||||
|
this._window.document.body.appendChild(this._notificationBar);
|
||||||
|
|
||||||
|
this._notificationBar.dataset.targetTourId = targetTour.id;
|
||||||
|
let notificationStrings = targetTour.getNotificationStrings(this._bundle);
|
||||||
|
let actionBtn = this._notificationBar.querySelector("#onboarding-notification-action-btn");
|
||||||
|
actionBtn.textContent = notificationStrings.button;
|
||||||
|
let tourTitle = this._notificationBar.querySelector("#onboarding-notification-tour-title");
|
||||||
|
tourTitle.textContent = notificationStrings.title;
|
||||||
|
let tourMessage = this._notificationBar.querySelector("#onboarding-notification-tour-message");
|
||||||
|
tourMessage.textContent = notificationStrings.message;
|
||||||
|
|
||||||
|
this._notificationBar.addEventListener("transitionend", () => {
|
||||||
|
this._notificationBar.dataset.cssTransition = "end";
|
||||||
|
}, { once: true });
|
||||||
|
this._window.requestAnimationFrame(() => {
|
||||||
|
// Request the 2nd animation frame.
|
||||||
|
// This is to make sure the appending operation above and the css operation happen
|
||||||
|
// in the different layout tick so as to make sure the transition happens.
|
||||||
|
this._window.requestAnimationFrame(() => this._notificationBar.classList.add("onboarding-opened"));
|
||||||
|
});
|
||||||
|
|
||||||
|
this.sendMessageToChrome("set-prefs", [{
|
||||||
|
name: "browser.onboarding.notification.lastPrompted",
|
||||||
|
value: targetTour.id
|
||||||
|
}]);
|
||||||
|
}
|
||||||
|
|
||||||
|
hideNotification() {
|
||||||
|
if (this._notificationBar) {
|
||||||
|
this._notificationBar.classList.remove("onboarding-opened");
|
||||||
|
delete this._notificationBar.dataset.cssTransition;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_renderNotificationBar() {
|
||||||
|
let div = this._window.document.createElement("div");
|
||||||
|
div.id = "onboarding-notification-bar";
|
||||||
|
// Here we use `innerHTML` is for more friendly reading.
|
||||||
|
// The security should be fine because this is not from an external input.
|
||||||
|
div.innerHTML = `
|
||||||
|
<div id="onboarding-notification-icon"></div>
|
||||||
|
<section id="onboarding-notification-message-section">
|
||||||
|
<div id="onboarding-notification-tour-icon"></div>
|
||||||
|
<div id="onboarding-notification-body">
|
||||||
|
<h6 id="onboarding-notification-tour-title"></h6>
|
||||||
|
<span id="onboarding-notification-tour-message"></span>
|
||||||
|
</div>
|
||||||
|
<button id="onboarding-notification-action-btn"></button>
|
||||||
|
</section>
|
||||||
|
<button id="onboarding-notification-close-btn"></button>
|
||||||
|
`;
|
||||||
|
let toolTip = this._bundle.formatStringFromName("onboarding.notification-icon-tool-tip", [BRAND_SHORT_NAME], 1);
|
||||||
|
div.querySelector("#onboarding-notification-icon").setAttribute("data-tooltip", toolTip);
|
||||||
|
return div;
|
||||||
|
}
|
||||||
|
|
||||||
hide() {
|
hide() {
|
||||||
this.sendMessageToChrome("set-prefs", [
|
this.sendMessageToChrome("set-prefs", [
|
||||||
{
|
{
|
||||||
|
@ -279,7 +453,6 @@ class Onboarding {
|
||||||
div.id = "onboarding-overlay";
|
div.id = "onboarding-overlay";
|
||||||
// Here we use `innerHTML` is for more friendly reading.
|
// Here we use `innerHTML` is for more friendly reading.
|
||||||
// The security should be fine because this is not from an external input.
|
// The security should be fine because this is not from an external input.
|
||||||
// We're not shipping yet so l10n strings is going to be closed for now.
|
|
||||||
div.innerHTML = `
|
div.innerHTML = `
|
||||||
<div id="onboarding-overlay-dialog">
|
<div id="onboarding-overlay-dialog">
|
||||||
<span id="onboarding-overlay-close-btn"></span>
|
<span id="onboarding-overlay-close-btn"></span>
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
# 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
|
# 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/.
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
# LOCALIZATION NOTE(onboarding.tour-title): This string will be used in the overlay title. %S is brandShortName
|
# LOCALIZATION NOTE(onboarding.overlay-title): This string will be used in the overlay title. %S is brandShortName
|
||||||
onboarding.overlay-title=Getting started with %S
|
onboarding.overlay-title=Getting started with %S
|
||||||
|
|
||||||
onboarding.tour-search=One-Click Search
|
onboarding.tour-search=One-Click Search
|
||||||
onboarding.tour-search.title=Find the needle or the haystack.
|
onboarding.tour-search.title=Find the needle or the haystack.
|
||||||
|
|
||||||
# LOCALIZATION NOTE (onboarding.tour-search.description): If Amazon is not part
|
# LOCALIZATION NOTE (onboarding.tour-search.description): If Amazon is not part
|
||||||
# of the default searchplugins for your locale, you can replace it with another
|
# of the default searchplugins for your locale, you can replace it with another
|
||||||
# ecommerce website (if you're shipping one), but not with a general purpose
|
# ecommerce website (if you're shipping one), but not with a general purpose
|
||||||
|
@ -13,33 +13,52 @@ onboarding.tour-search.title=Find the needle or the haystack.
|
||||||
# Wikipedia and drop Amazon from the text.
|
# Wikipedia and drop Amazon from the text.
|
||||||
onboarding.tour-search.description=Having a default search engine doesn’t mean it’s the only one you use. Pick a search engine or a site, like Amazon or Wikipedia, to search on the fly.
|
onboarding.tour-search.description=Having a default search engine doesn’t mean it’s the only one you use. Pick a search engine or a site, like Amazon or Wikipedia, to search on the fly.
|
||||||
onboarding.tour-search.button=Open One-Click Search
|
onboarding.tour-search.button=Open One-Click Search
|
||||||
|
onboarding.notification.onboarding-tour-search.title=Find it faster.
|
||||||
|
onboarding.notification.onboarding-tour-search.message=Access all of your favorite search engines with a click. Search the whole Web or just one website right from the search box.
|
||||||
|
|
||||||
onboarding.tour-private-browsing=Private Browsing
|
onboarding.tour-private-browsing=Private Browsing
|
||||||
onboarding.tour-private-browsing.title=A little privacy goes a long way.
|
onboarding.tour-private-browsing.title=A little privacy goes a long way.
|
||||||
|
|
||||||
# LOCALIZATION NOTE(onboarding.tour-private-browsing.description): %S is brandShortName.
|
# LOCALIZATION NOTE(onboarding.tour-private-browsing.description): %S is brandShortName.
|
||||||
onboarding.tour-private-browsing.description=Browse the internet without saving your searches or the sites you visited. When your session ends, the cookies disappear from %S like they were never there.
|
onboarding.tour-private-browsing.description=Browse the internet without saving your searches or the sites you visited. When your session ends, the cookies disappear from %S like they were never there.
|
||||||
onboarding.tour-private-browsing.button=Show Private Browsing in Menu
|
onboarding.tour-private-browsing.button=Show Private Browsing in Menu
|
||||||
onboarding.hidden-checkbox-label=Hide the tour
|
onboarding.notification.onboarding-tour-private-browsing.title=Browse by yourself.
|
||||||
|
onboarding.notification.onboarding-tour-private-browsing.message=There’s no reason to share your online life with trackers every time you browse. Want to keep something to yourself? Use Private Browsing with Tracking Protection.
|
||||||
|
|
||||||
onboarding.tour-addons=Add-ons
|
onboarding.tour-addons=Add-ons
|
||||||
onboarding.tour-addons.title=Add more functionality.
|
onboarding.tour-addons.title=Add more functionality.
|
||||||
|
onboarding.notification.onboarding-tour-addons.title=Get more done.
|
||||||
|
# LOCALIZATION NOTE(onboarding.notification.onboarding-tour-addons.message): %S is brandShortName.
|
||||||
|
onboarding.notification.onboarding-tour-addons.message=Add-ons are small apps you can add to %S that do lots of things — from managing to-do lists, to downloading videos, to changing the look of your browser.
|
||||||
|
|
||||||
# LOCALIZATION NOTE(onboarding.tour-addons.description): This string will be used in the add-on tour description. %1$S is brandShortName
|
# LOCALIZATION NOTE(onboarding.tour-addons.description): This string will be used in the add-on tour description. %1$S is brandShortName
|
||||||
onboarding.tour-addons.description=Add-ons expand %1$S’s built-in features, so %1$S works the way you do. Compare prices, check the weather or express your personality with a custom theme.
|
onboarding.tour-addons.description=Add-ons expand %1$S’s built-in features, so %1$S works the way you do. Compare prices, check the weather or express your personality with a custom theme.
|
||||||
onboarding.tour-addons.button=Show Add-ons in Menu
|
onboarding.tour-addons.button=Show Add-ons in Menu
|
||||||
onboarding.tour-customize=Customize
|
onboarding.tour-customize=Customize
|
||||||
onboarding.tour-customize.title=Do things your way.
|
onboarding.tour-customize.title=Do things your way.
|
||||||
|
|
||||||
# LOCALIZATION NOTE(onboarding.tour-customize.description): This string will be used in the customize tour description. %S is brandShortName
|
# LOCALIZATION NOTE(onboarding.tour-customize.description): This string will be used in the customize tour description. %S is brandShortName
|
||||||
onboarding.tour-customize.description=Drag, drop, and reorder %S’s toolbar and menu to fit your needs. You can even select a compact theme to give websites more room.
|
onboarding.tour-customize.description=Drag, drop, and reorder %S’s toolbar and menu to fit your needs. You can even select a compact theme to give websites more room.
|
||||||
onboarding.tour-customize.button=Show Customize in Menu
|
onboarding.tour-customize.button=Show Customize in Menu
|
||||||
|
onboarding.notification.onboarding-tour-customize.title=Rearrange your toolbar.
|
||||||
|
# LOCALIZATION NOTE(onboarding.notification.onboarding-tour-customize.message): %S is brandShortName.
|
||||||
|
onboarding.notification.onboarding-tour-customize.message=Put the tools you use most right at your fingertips. Add more options to your toolbar. Or select a theme to make %S reflect your personality.
|
||||||
|
|
||||||
onboarding.tour-default-browser=Default Browser
|
onboarding.tour-default-browser=Default Browser
|
||||||
onboarding.tour-default-browser.title=We’re there for you.
|
onboarding.tour-default-browser.title=We’re there for you.
|
||||||
|
|
||||||
# LOCALIZATION NOTE(onboarding.tour-default-browser.description): This string will be used in the default browser tour description. %1$S is brandShortName
|
# LOCALIZATION NOTE(onboarding.tour-default-browser.description): This string will be used in the default browser tour description. %1$S is brandShortName
|
||||||
onboarding.tour-default-browser.description=Love %1$S? Set it as your default browser. Then when you open a link from another application, %1$S has you covered.
|
onboarding.tour-default-browser.description=Love %1$S? Set it as your default browser. Then when you open a link from another application, %1$S has you covered.
|
||||||
|
|
||||||
# LOCALIZATION NOTE(onboarding.tour-default-browser.button): Label for a button to open the OS default browser settings where it's not possible to set the default browser directly. (OSX, Linux, Windows 8 and higher)
|
# LOCALIZATION NOTE(onboarding.tour-default-browser.button): Label for a button to open the OS default browser settings where it's not possible to set the default browser directly. (OSX, Linux, Windows 8 and higher)
|
||||||
onboarding.tour-default-browser.button=Open Default Browser Settings
|
onboarding.tour-default-browser.button=Open Default Browser Settings
|
||||||
|
|
||||||
# LOCALIZATION NOTE(onboarding.tour-default-browser.win7.button): Label for a button to directly set the default browser (Windows 7). %S is brandShortName
|
# LOCALIZATION NOTE(onboarding.tour-default-browser.win7.button): Label for a button to directly set the default browser (Windows 7). %S is brandShortName
|
||||||
onboarding.tour-default-browser.win7.button=Make %S Your Default Browser
|
onboarding.tour-default-browser.win7.button=Make %S Your Default Browser
|
||||||
|
# LOCALIZATION NOTE(onboarding.notification.onboarding-tour-default-browser.title): %S is brandShortName.
|
||||||
|
onboarding.notification.onboarding-tour-default-browser.title=Make %S your go-to browser.
|
||||||
|
# LOCALIZATION NOTE(onboarding.notification.onboarding-tour-default-browser.message): %1$S is brandShortName
|
||||||
|
onboarding.notification.onboarding-tour-default-browser.message=It doesn’t take much to get the most from %1$S. Just set %1$S as your default browser and put control, customization, and protection on autopilot.
|
||||||
|
|
||||||
|
onboarding.hidden-checkbox-label=Hide the tour
|
||||||
|
|
||||||
|
#LOCALIZATION NOTE(onboarding.button.learnMore): this string is used as a button label, displayed near the message, and shared across all the onboarding notifications.
|
||||||
|
onboarding.button.learnMore=Learn More
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE(onboarding.notification-icon-tool-tip): %S is brandShortName.
|
||||||
|
onboarding.notification-icon-tool-tip=New to %S?
|
||||||
|
|
|
@ -31,7 +31,7 @@ function promiseOnboardingOverlayOpened(browser) {
|
||||||
return ContentTask.spawn(browser, {}, function() {
|
return ContentTask.spawn(browser, {}, function() {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
let overlay = content.document.querySelector("#onboarding-overlay");
|
let overlay = content.document.querySelector("#onboarding-overlay");
|
||||||
if (overlay.classList.contains("opened")) {
|
if (overlay.classList.contains("onboarding-opened")) {
|
||||||
resolve(true);
|
resolve(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче