Bug 1467572 - Part 18: Show an onboarding tooltip for the setting menu button in RDM. r=jdescottes
Design https://mozilla.invisionapp.com/d/main#/console/12408235/300479943/preview
MozReview-Commit-ID: K1vIjMc685u
--- a/devtools/client/inspector/shared/three-pane-onboarding-tooltip.js
+++ b/devtools/client/inspector/shared/three-pane-onboarding-tooltip.js
@@ -29,45 +29,45 @@ class ThreePaneOnboardingTooltip {
type: "arrow",
useXulWrapper: true,
});
this.onCloseButtonClick = this.onCloseButtonClick.bind(this);
this.onLearnMoreLinkClick = this.onLearnMoreLinkClick.bind(this);
const container = doc.createElementNS(XHTML_NS, "div");
- container.className = "three-pane-onboarding-container";
+ container.className = "onboarding-container";
const icon = doc.createElementNS(XHTML_NS, "span");
- icon.className = "three-pane-onboarding-icon";
+ icon.className = "onboarding-icon";
container.appendChild(icon);
const content = doc.createElementNS(XHTML_NS, "div");
- content.className = "three-pane-onboarding-content";
+ content.className = "onboarding-content";
container.appendChild(content);
const message = doc.createElementNS(XHTML_NS, "div");
const learnMoreString = L10N.getStr("inspector.threePaneOnboarding.learnMoreLink");
const messageString = L10N.getFormatStr("inspector.threePaneOnboarding.content",
learnMoreString);
const learnMoreStartIndex = messageString.indexOf(learnMoreString);
message.append(messageString.substring(0, learnMoreStartIndex));
this.learnMoreLink = doc.createElementNS(XHTML_NS, "a");
- this.learnMoreLink.className = "three-pane-onboarding-link";
+ this.learnMoreLink.className = "onboarding-link";
this.learnMoreLink.href = "#";
this.learnMoreLink.textContent = learnMoreString;
message.append(this.learnMoreLink);
message.append(messageString.substring(learnMoreStartIndex + learnMoreString.length));
content.append(message);
this.closeButton = doc.createElementNS(XHTML_NS, "button");
- this.closeButton.className = "three-pane-onboarding-close-button devtools-button";
+ this.closeButton.className = "onboarding-close-button devtools-button";
container.appendChild(this.closeButton);
this.closeButton.addEventListener("click", this.onCloseButtonClick);
this.learnMoreLink.addEventListener("click", this.onLearnMoreLinkClick);
this.tooltip.setContent(container, { width: CONTAINER_WIDTH });
this.tooltip.show(this.doc.querySelector("#inspector-sidebar .sidebar-toggle"), {
position: "top",
--- a/devtools/client/locales/en-US/responsive.properties
+++ b/devtools/client/locales/en-US/responsive.properties
@@ -127,8 +127,13 @@ responsive.reloadConditions.userAgent=Re
# LOCALIZATION NOTE (responsive.reloadNotification.description): Text in notification bar
# shown on first open to clarify that some features need a reload to apply. %1$S is the
# label on the reload conditions menu (responsive.reloadConditions.label).
responsive.reloadNotification.description=Device simulation changes require a reload to fully apply. Automatic reloads are disabled by default to avoid losing any changes in DevTools. You can enable reloading via the ā%1$Sā menu.
# LOCALIZATION NOTE (responsive.leftAlignViewport): Label on checkbox used in the settings
# menu.
responsive.leftAlignViewport = Left-align Viewport
+
+# LOCALIZATION NOTE (responsive.settingOnboarding.content): This is the content shown in
+# the setting onboarding tooltip that is displayed below the settings menu button in
+# Responsive Design Mode.
+responsive.settingOnboarding.content=New: Change to left-alignment or edit reload behavior here.
--- a/devtools/client/preferences/devtools-client.js
+++ b/devtools/client/preferences/devtools-client.js
@@ -313,16 +313,22 @@ pref("devtools.editor.autocomplete", tru
// Whether or not the viewports are left aligned.
pref("devtools.responsive.leftAlignViewport.enabled", false);
// Whether to reload when touch simulation is toggled
pref("devtools.responsive.reloadConditions.touchSimulation", false);
// Whether to reload when user agent is changed
pref("devtools.responsive.reloadConditions.userAgent", false);
// Whether to show the notification about reloading to apply emulation
pref("devtools.responsive.reloadNotification.enabled", true);
+// Whether to show the settings onboarding tooltip only in release or beta builds.
+#if defined(RELEASE_OR_BETA)
+pref("devtools.responsive.show-setting-tooltip", true);
+#else
+pref("devtools.responsive.show-setting-tooltip", false);
+#endif
// Enable new about:debugging.
pref("devtools.aboutdebugging.new-enabled", false);
pref("devtools.aboutdebugging.network-locations", "[]");
// about:debugging: only show system add-ons in local builds by default.
#ifdef MOZILLA_OFFICIAL
pref("devtools.aboutdebugging.showSystemAddons", false);
--- a/devtools/client/responsive.html/manager.js
+++ b/devtools/client/responsive.html/manager.js
@@ -9,29 +9,31 @@ const promise = require("promise");
const Services = require("Services");
const EventEmitter = require("devtools/shared/event-emitter");
const TOOL_URL = "chrome://devtools/content/responsive.html/index.xhtml";
loader.lazyRequireGetter(this, "DebuggerClient", "devtools/shared/client/debugger-client", true);
loader.lazyRequireGetter(this, "DebuggerServer", "devtools/server/main", true);
loader.lazyRequireGetter(this, "throttlingProfiles", "devtools/client/shared/components/throttling/profiles");
+loader.lazyRequireGetter(this, "SettingOnboardingTooltip", "devtools/client/responsive.html/setting-onboarding-tooltip");
loader.lazyRequireGetter(this, "swapToInnerBrowser", "devtools/client/responsive.html/browser/swap", true);
loader.lazyRequireGetter(this, "startup", "devtools/client/responsive.html/utils/window", true);
loader.lazyRequireGetter(this, "message", "devtools/client/responsive.html/utils/message");
loader.lazyRequireGetter(this, "showNotification", "devtools/client/responsive.html/utils/notification", true);
loader.lazyRequireGetter(this, "l10n", "devtools/client/responsive.html/utils/l10n");
loader.lazyRequireGetter(this, "EmulationFront", "devtools/shared/fronts/emulation", true);
loader.lazyRequireGetter(this, "PriorityLevels", "devtools/client/shared/components/NotificationBox", true);
loader.lazyRequireGetter(this, "TargetFactory", "devtools/client/framework/target", true);
loader.lazyRequireGetter(this, "gDevTools", "devtools/client/framework/devtools", true);
loader.lazyRequireGetter(this, "Telemetry", "devtools/client/shared/telemetry");
const RELOAD_CONDITION_PREF_PREFIX = "devtools.responsive.reloadConditions.";
const RELOAD_NOTIFICATION_PREF = "devtools.responsive.reloadNotification.enabled";
+const SHOW_SETTING_TOOLTIP_PREF = "devtools.responsive.show-setting-tooltip";
function debug(msg) {
// console.log(`RDM manager: ${msg}`);
}
/**
* ResponsiveUIManager is the external API for the browser UI, etc. to use when
* opening and closing the responsive UI.
@@ -372,16 +374,22 @@ ResponsiveUI.prototype = {
// Notify the inner browser to start the frame script
debug("Wait until start frame script");
await message.request(this.toolWindow, "start-frame-script");
// Get the protocol ready to speak with emulation actor
debug("Wait until RDP server connect");
await this.connectToServer();
+ // Show the settings onboarding tooltip
+ if (Services.prefs.getBoolPref(SHOW_SETTING_TOOLTIP_PREF)) {
+ this.settingOnboardingTooltip =
+ new SettingOnboardingTooltip(ui.toolWindow.document);
+ }
+
// Non-blocking message to tool UI to start any delayed init activities
message.post(this.toolWindow, "post-init");
debug("Init done");
},
/**
* Close RDM and restore page content back into a regular tab.
@@ -431,16 +439,21 @@ ResponsiveUI.prototype = {
this.reloadOnChange("userAgent");
reloadNeeded |= await this.updateTouchSimulation() &&
this.reloadOnChange("touchSimulation");
if (reloadNeeded) {
this.getViewportBrowser().reload();
}
}
+ if (this.settingOnboardingTooltip) {
+ this.settingOnboardingTooltip.destroy();
+ this.settingOnboardingTooltip = null;
+ }
+
// Destroy local state
const swap = this.swap;
this.browserWindow = null;
this.tab = null;
this.inited = null;
this.toolWindow = null;
this.swap = null;
--- a/devtools/client/responsive.html/moz.build
+++ b/devtools/client/responsive.html/moz.build
@@ -16,16 +16,17 @@ DIRS += [
DevToolsModules(
'commands.js',
'constants.js',
'index.css',
'index.js',
'manager.js',
'reducers.js',
'responsive-ua.css',
+ 'setting-onboarding-tooltip.js',
'store.js',
'types.js',
)
XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
BROWSER_CHROME_MANIFESTS += ['test/browser/browser.ini']
with Files('**'):
new file mode 100644
--- /dev/null
+++ b/devtools/client/responsive.html/setting-onboarding-tooltip.js
@@ -0,0 +1,71 @@
+/* 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/. */
+
+"use strict";
+
+const Services = require("Services");
+const { HTMLTooltip } = require("devtools/client/shared/widgets/tooltip/HTMLTooltip");
+
+const { getStr } = require("./utils/l10n");
+
+const SHOW_SETTING_TOOLTIP_PREF = "devtools.responsive.show-setting-tooltip";
+
+const CONTAINER_WIDTH = 270;
+
+/**
+ * Setting onboarding tooltip that is shown on the setting menu button in the RDM toolbar
+ * when the pref is on.
+ */
+class SettingOnboardingTooltip {
+ constructor(doc) {
+ this.doc = doc;
+ this.tooltip = new HTMLTooltip(this.doc, { type: "arrow" });
+
+ this.onCloseButtonClick = this.onCloseButtonClick.bind(this);
+
+ const container = doc.createElement("div");
+ container.className = "onboarding-container";
+
+ const icon = doc.createElement("span");
+ icon.className = "onboarding-icon";
+ container.appendChild(icon);
+
+ const content = doc.createElement("div");
+ content.className = "onboarding-content";
+ content.textContent = getStr("responsive.settingOnboarding.content");
+ container.appendChild(content);
+
+ this.closeButton = doc.createElement("button");
+ this.closeButton.className = "onboarding-close-button devtools-button";
+ container.appendChild(this.closeButton);
+
+ this.closeButton.addEventListener("click", this.onCloseButtonClick);
+
+ this.tooltip.setContent(container, { width: CONTAINER_WIDTH });
+ this.tooltip.show(this.doc.getElementById("settings-button"), {
+ position: "bottom",
+ });
+ }
+
+ destroy() {
+ this.closeButton.removeEventListener("click", this.onCloseButtonClick);
+
+ this.tooltip.destroy();
+
+ this.closeButton = null;
+ this.doc = null;
+ this.tooltip = null;
+ }
+
+ /**
+ * Handler for the "click" event on the close button. Hides the onboarding tooltip
+ * and sets the show three pane onboarding tooltip pref to false.
+ */
+ onCloseButtonClick() {
+ Services.prefs.setBoolPref(SHOW_SETTING_TOOLTIP_PREF, false);
+ this.tooltip.hide();
+ }
+}
+
+module.exports = SettingOnboardingTooltip;
--- a/devtools/client/responsive.html/test/browser/head.js
+++ b/devtools/client/responsive.html/test/browser/head.js
@@ -50,23 +50,26 @@ SimpleTest.waitForExplicitFinish();
// on debug builds. Usually we are just barely over the limit, so a blanket factor of 2
// should be enough.
requestLongerTimeout(2);
Services.prefs.setCharPref("devtools.devices.url", TEST_URI_ROOT + "devices.json");
// The appearance of this notification causes intermittent behavior in some tests that
// send mouse events, since it causes the content to shift when it appears.
Services.prefs.setBoolPref("devtools.responsive.reloadNotification.enabled", false);
+// Don't show the setting onboarding tooltip in the test suites.
+Services.prefs.setBoolPref("devtools.responsive.show-setting-tooltip", false);
registerCleanupFunction(async () => {
Services.prefs.clearUserPref("devtools.devices.url");
Services.prefs.clearUserPref("devtools.responsive.reloadNotification.enabled");
Services.prefs.clearUserPref("devtools.responsive.html.displayedDeviceList");
Services.prefs.clearUserPref("devtools.responsive.reloadConditions.touchSimulation");
Services.prefs.clearUserPref("devtools.responsive.reloadConditions.userAgent");
+ Services.prefs.clearUserPref("devtools.responsive.show-setting-tooltip");
await asyncStorage.removeItem("devtools.devices.url_cache");
await removeLocalDevices();
});
/**
* Open responsive design mode for the given tab.
*/
var openRDM = async function(tab) {
--- a/devtools/client/themes/tooltips.css
+++ b/devtools/client/themes/tooltips.css
@@ -558,57 +558,57 @@
/* Tooltip: Image tooltip */
.devtools-tooltip-image-broken {
box-sizing: border-box;
height: 100%;
padding: 7px;
}
-/* Tooltip: 3 Pane Inspecot Onboarding Tooltip */
+/* Tooltip: Onboarding Tooltip */
-.three-pane-onboarding-container {
+.onboarding-container {
align-items: center;
background-color: var(--theme-toolbar-background);
box-sizing: border-box;
color: var(--theme-body-color);
display: flex;
font-size: 12px;
padding: 7px;
width: 100%;
-moz-user-select: none;
}
-.three-pane-onboarding-icon {
+.onboarding-icon {
display: inline-block;
background-size: 21px;
width: 21px;
height: 21px;
margin: 8px;
background-image: url("chrome://devtools/skin/images/fox-smiling.svg");
}
-.three-pane-onboarding-content {
+.onboarding-content {
flex: 1;
padding-inline-start: 5px;
}
-.three-pane-onboarding-link {
+.onboarding-link {
color: var(--onboarding-link-color);
cursor: pointer;
}
-.three-pane-onboarding-link:hover {
+.onboarding-link:hover {
text-decoration: underline;
}
-.three-pane-onboarding-link:active {
+.onboarding-link:active {
color: var(--onboarding-link-active-color);
}
-.three-pane-onboarding-close-button {
+.onboarding-close-button {
align-self: flex-start;
}
-.three-pane-onboarding-close-button::before {
+.onboarding-close-button::before {
background-image: url("chrome://devtools/skin/images/close.svg");
margin: -6px 0 0 -6px;
}